@bilalimamoglu/sift 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/cli.js +26 -16
- package/dist/index.d.ts +2 -1
- package/dist/index.js +28 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,9 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
Your AI agent should not be reading 13,000 lines of test output.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
If 125 tests fail for one reason, it should pay for that reason once.
|
|
12
|
+
|
|
13
|
+
`sift` turns noisy command output into a short, structured diagnosis for coding agents, so they spend fewer tokens, cost less to run, and move through debug loops faster.
|
|
14
|
+
|
|
15
|
+
Instead of feeding an agent thousands of lines of logs, you give it:
|
|
16
|
+
- the root cause
|
|
17
|
+
- where it happens
|
|
18
|
+
- what to fix
|
|
19
|
+
- what to do next
|
|
14
20
|
|
|
15
21
|
```bash
|
|
16
22
|
sift exec --preset test-status -- pytest -q
|
|
@@ -28,13 +34,14 @@ sift exec --preset test-status -- pytest -q
|
|
|
28
34
|
- Decision: stop and act.
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
On the largest real fixture in the benchmark:
|
|
38
|
+
`198K` raw-output tokens -> `129` `standard` tokens.
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
Same diagnosis. Far less work.
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
## What it is
|
|
36
43
|
|
|
37
|
-
`sift` sits between
|
|
44
|
+
`sift` sits between a noisy command and a coding agent. It captures output, groups repeated failures into root-cause buckets, and returns a short diagnosis with an anchor, a likely fix, and a decision signal.
|
|
38
45
|
|
|
39
46
|
## Install
|
|
40
47
|
|
package/dist/cli.js
CHANGED
|
@@ -7594,7 +7594,7 @@ function buildGenericRawSlice(args) {
|
|
|
7594
7594
|
|
|
7595
7595
|
// src/core/run.ts
|
|
7596
7596
|
var RETRY_DELAY_MS = 300;
|
|
7597
|
-
var
|
|
7597
|
+
var PENDING_NOTICE_DELAY_MS = 150;
|
|
7598
7598
|
function estimateTokenCount(text) {
|
|
7599
7599
|
return Math.max(1, Math.ceil(text.length / 4));
|
|
7600
7600
|
}
|
|
@@ -7675,17 +7675,16 @@ function buildDryRunOutput(args) {
|
|
|
7675
7675
|
async function delay(ms) {
|
|
7676
7676
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
7677
7677
|
}
|
|
7678
|
-
function
|
|
7679
|
-
if (!
|
|
7678
|
+
function startPendingNotice(message, enabled) {
|
|
7679
|
+
if (!enabled) {
|
|
7680
7680
|
return () => {
|
|
7681
7681
|
};
|
|
7682
7682
|
}
|
|
7683
|
-
const message = "sift waiting for provider...";
|
|
7684
7683
|
let shown = false;
|
|
7685
7684
|
const timer = setTimeout(() => {
|
|
7686
7685
|
shown = true;
|
|
7687
7686
|
process.stderr.write(`${message}\r`);
|
|
7688
|
-
},
|
|
7687
|
+
}, PENDING_NOTICE_DELAY_MS);
|
|
7689
7688
|
return () => {
|
|
7690
7689
|
clearTimeout(timer);
|
|
7691
7690
|
if (!shown) {
|
|
@@ -7715,7 +7714,10 @@ async function generateWithRetry(args) {
|
|
|
7715
7714
|
responseMode: args.responseMode,
|
|
7716
7715
|
jsonResponseFormat: args.request.config.provider.jsonResponseFormat
|
|
7717
7716
|
});
|
|
7718
|
-
const stopPendingNotice =
|
|
7717
|
+
const stopPendingNotice = startPendingNotice(
|
|
7718
|
+
"sift waiting for provider...",
|
|
7719
|
+
Boolean(process.stderr.isTTY)
|
|
7720
|
+
);
|
|
7719
7721
|
try {
|
|
7720
7722
|
try {
|
|
7721
7723
|
return await generate();
|
|
@@ -9281,6 +9283,10 @@ async function runExec(request) {
|
|
|
9281
9283
|
cwd: commandCwd,
|
|
9282
9284
|
stdio: ["inherit", "pipe", "pipe"]
|
|
9283
9285
|
});
|
|
9286
|
+
const stopChildPendingNotice = startPendingNotice(
|
|
9287
|
+
"sift waiting for child command...",
|
|
9288
|
+
Boolean(process.stderr.isTTY) && !request.quiet
|
|
9289
|
+
);
|
|
9284
9290
|
const handleChunk = (chunk) => {
|
|
9285
9291
|
const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
|
|
9286
9292
|
if (bypassed) {
|
|
@@ -9301,21 +9307,25 @@ async function runExec(request) {
|
|
|
9301
9307
|
};
|
|
9302
9308
|
child.stdout.on("data", handleChunk);
|
|
9303
9309
|
child.stderr.on("data", handleChunk);
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9310
|
+
try {
|
|
9311
|
+
await new Promise((resolve, reject) => {
|
|
9312
|
+
child.on("error", (error) => {
|
|
9313
|
+
reject(error);
|
|
9314
|
+
});
|
|
9315
|
+
child.on("close", (status, signal) => {
|
|
9316
|
+
childStatus = status;
|
|
9317
|
+
childSignal = signal;
|
|
9318
|
+
resolve();
|
|
9319
|
+
});
|
|
9312
9320
|
});
|
|
9313
|
-
}
|
|
9321
|
+
} catch (error) {
|
|
9314
9322
|
if (error instanceof Error) {
|
|
9315
9323
|
throw error;
|
|
9316
9324
|
}
|
|
9317
9325
|
throw new Error("Failed to start child process.");
|
|
9318
|
-
}
|
|
9326
|
+
} finally {
|
|
9327
|
+
stopChildPendingNotice();
|
|
9328
|
+
}
|
|
9319
9329
|
const exitCode = normalizeChildExitCode(childStatus, childSignal);
|
|
9320
9330
|
const capturedOutput = capture.render();
|
|
9321
9331
|
const autoWatchDetected = !request.watch && looksLikeWatchStream(capturedOutput);
|
package/dist/index.d.ts
CHANGED
|
@@ -162,6 +162,7 @@ interface RunResult {
|
|
|
162
162
|
stats: RunStats | null;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
declare function startPendingNotice(message: string, enabled: boolean): () => void;
|
|
165
166
|
declare function runSift(request: RunRequest): Promise<string>;
|
|
166
167
|
declare function runSiftWithStats(request: RunRequest): Promise<RunResult>;
|
|
167
168
|
|
|
@@ -178,4 +179,4 @@ interface ResolveOptions {
|
|
|
178
179
|
}
|
|
179
180
|
declare function resolveConfig(options?: ResolveOptions): SiftConfig;
|
|
180
181
|
|
|
181
|
-
export { BoundedCapture, type DetailLevel, type ExecRequest, type GenerateInput, type GenerateResult, type Goal, type InputConfig, type JsonResponseFormatMode, type LLMProvider, type NativeProviderName, type OutputFormat, type PartialSiftConfig, type PreparedInput, type PresetDefinition, type PromptPolicyName, type ProviderConfig, type ProviderName, type ProviderProfile, type ProviderProfiles, type RawSliceStrategy, type ResolveOptions, type ResponseMode, type RunRequest, type RuntimeConfig, type SiftConfig, type TestStatusRemainingMode, type UsageInfo, buildCommandPreview, getExecSuccessShortcut, looksInteractivePrompt, mergeDefined, normalizeChildExitCode, resolveConfig, runExec, runSift, runSiftWithStats };
|
|
182
|
+
export { BoundedCapture, type DetailLevel, type ExecRequest, type GenerateInput, type GenerateResult, type Goal, type InputConfig, type JsonResponseFormatMode, type LLMProvider, type NativeProviderName, type OutputFormat, type PartialSiftConfig, type PreparedInput, type PresetDefinition, type PromptPolicyName, type ProviderConfig, type ProviderName, type ProviderProfile, type ProviderProfiles, type RawSliceStrategy, type ResolveOptions, type ResponseMode, type RunRequest, type RuntimeConfig, type SiftConfig, type TestStatusRemainingMode, type UsageInfo, buildCommandPreview, getExecSuccessShortcut, looksInteractivePrompt, mergeDefined, normalizeChildExitCode, resolveConfig, runExec, runSift, runSiftWithStats, startPendingNotice };
|
package/dist/index.js
CHANGED
|
@@ -5774,7 +5774,7 @@ function buildGenericRawSlice(args) {
|
|
|
5774
5774
|
|
|
5775
5775
|
// src/core/run.ts
|
|
5776
5776
|
var RETRY_DELAY_MS = 300;
|
|
5777
|
-
var
|
|
5777
|
+
var PENDING_NOTICE_DELAY_MS = 150;
|
|
5778
5778
|
function estimateTokenCount(text) {
|
|
5779
5779
|
return Math.max(1, Math.ceil(text.length / 4));
|
|
5780
5780
|
}
|
|
@@ -5855,17 +5855,16 @@ function buildDryRunOutput(args) {
|
|
|
5855
5855
|
async function delay(ms) {
|
|
5856
5856
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
5857
5857
|
}
|
|
5858
|
-
function
|
|
5859
|
-
if (!
|
|
5858
|
+
function startPendingNotice(message, enabled) {
|
|
5859
|
+
if (!enabled) {
|
|
5860
5860
|
return () => {
|
|
5861
5861
|
};
|
|
5862
5862
|
}
|
|
5863
|
-
const message = "sift waiting for provider...";
|
|
5864
5863
|
let shown = false;
|
|
5865
5864
|
const timer = setTimeout(() => {
|
|
5866
5865
|
shown = true;
|
|
5867
5866
|
process.stderr.write(`${message}\r`);
|
|
5868
|
-
},
|
|
5867
|
+
}, PENDING_NOTICE_DELAY_MS);
|
|
5869
5868
|
return () => {
|
|
5870
5869
|
clearTimeout(timer);
|
|
5871
5870
|
if (!shown) {
|
|
@@ -5895,7 +5894,10 @@ async function generateWithRetry(args) {
|
|
|
5895
5894
|
responseMode: args.responseMode,
|
|
5896
5895
|
jsonResponseFormat: args.request.config.provider.jsonResponseFormat
|
|
5897
5896
|
});
|
|
5898
|
-
const stopPendingNotice =
|
|
5897
|
+
const stopPendingNotice = startPendingNotice(
|
|
5898
|
+
"sift waiting for provider...",
|
|
5899
|
+
Boolean(process.stderr.isTTY)
|
|
5900
|
+
);
|
|
5899
5901
|
try {
|
|
5900
5902
|
try {
|
|
5901
5903
|
return await generate();
|
|
@@ -7293,6 +7295,10 @@ async function runExec(request) {
|
|
|
7293
7295
|
cwd: commandCwd,
|
|
7294
7296
|
stdio: ["inherit", "pipe", "pipe"]
|
|
7295
7297
|
});
|
|
7298
|
+
const stopChildPendingNotice = startPendingNotice(
|
|
7299
|
+
"sift waiting for child command...",
|
|
7300
|
+
Boolean(process.stderr.isTTY) && !request.quiet
|
|
7301
|
+
);
|
|
7296
7302
|
const handleChunk = (chunk) => {
|
|
7297
7303
|
const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
|
|
7298
7304
|
if (bypassed) {
|
|
@@ -7313,21 +7319,25 @@ async function runExec(request) {
|
|
|
7313
7319
|
};
|
|
7314
7320
|
child.stdout.on("data", handleChunk);
|
|
7315
7321
|
child.stderr.on("data", handleChunk);
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7322
|
+
try {
|
|
7323
|
+
await new Promise((resolve, reject) => {
|
|
7324
|
+
child.on("error", (error) => {
|
|
7325
|
+
reject(error);
|
|
7326
|
+
});
|
|
7327
|
+
child.on("close", (status, signal) => {
|
|
7328
|
+
childStatus = status;
|
|
7329
|
+
childSignal = signal;
|
|
7330
|
+
resolve();
|
|
7331
|
+
});
|
|
7324
7332
|
});
|
|
7325
|
-
}
|
|
7333
|
+
} catch (error) {
|
|
7326
7334
|
if (error instanceof Error) {
|
|
7327
7335
|
throw error;
|
|
7328
7336
|
}
|
|
7329
7337
|
throw new Error("Failed to start child process.");
|
|
7330
|
-
}
|
|
7338
|
+
} finally {
|
|
7339
|
+
stopChildPendingNotice();
|
|
7340
|
+
}
|
|
7331
7341
|
const exitCode = normalizeChildExitCode(childStatus, childSignal);
|
|
7332
7342
|
const capturedOutput = capture.render();
|
|
7333
7343
|
const autoWatchDetected = !request.watch && looksLikeWatchStream(capturedOutput);
|
|
@@ -7853,5 +7863,6 @@ export {
|
|
|
7853
7863
|
resolveConfig,
|
|
7854
7864
|
runExec,
|
|
7855
7865
|
runSift,
|
|
7856
|
-
runSiftWithStats
|
|
7866
|
+
runSiftWithStats,
|
|
7867
|
+
startPendingNotice
|
|
7857
7868
|
};
|