claude-yes 1.24.2 → 1.25.0
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 +136 -38
- package/dist/claude-yes.js +297 -155
- package/dist/cli.js +297 -155
- package/dist/cli.js.map +10 -5
- package/dist/codex-yes.js +297 -155
- package/dist/copilot-yes.js +297 -155
- package/dist/cursor-yes.js +297 -155
- package/dist/gemini-yes.js +297 -155
- package/dist/grok-yes.js +297 -155
- package/dist/index.js +226 -105
- package/dist/index.js.map +10 -5
- package/dist/qwen-yes.js +12093 -0
- package/package.json +38 -4
- package/ts/cli-idle.spec.ts +15 -12
- package/ts/cli.spec.ts +18 -0
- package/ts/cli.ts +74 -40
- package/ts/defineConfig.ts +12 -0
- package/ts/index.ts +166 -159
- package/ts/postbuild.ts +6 -4
- package/ts/runningLock.spec.ts +45 -31
- package/ts/tryCatch.ts +25 -0
- package/ts/utils.ts +20 -0
- package/ts/yesLog.ts +27 -0
- package/ts/cli.test.ts +0 -63
package/ts/utils.ts
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
export function sleepms(ms: number) {
|
|
2
2
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
3
|
}
|
|
4
|
+
export function deepMixin<T>(target: T, source: DeepPartial<T>): T {
|
|
5
|
+
for (const key in source) {
|
|
6
|
+
if (
|
|
7
|
+
source[key] &&
|
|
8
|
+
typeof source[key] === 'object' &&
|
|
9
|
+
!Array.isArray(source[key])
|
|
10
|
+
) {
|
|
11
|
+
if (!target[key] || typeof target[key] !== 'object') {
|
|
12
|
+
(target as any)[key] = {};
|
|
13
|
+
}
|
|
14
|
+
deepMixin(target[key], source[key] as any);
|
|
15
|
+
} else if (source[key] !== undefined) {
|
|
16
|
+
(target as any)[key] = source[key];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return target;
|
|
20
|
+
}
|
|
21
|
+
export type DeepPartial<T> = {
|
|
22
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
23
|
+
};
|
package/ts/yesLog.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { appendFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import tsaComposer from 'tsa-composer';
|
|
3
|
+
import { catcher } from './tryCatch';
|
|
4
|
+
|
|
5
|
+
let initial = true;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Log messages to agent-yes.log file
|
|
9
|
+
* Each message is appended as a new line
|
|
10
|
+
* The log file is cleared on the first call
|
|
11
|
+
*
|
|
12
|
+
* use only for debug, enabled when process.env.VERBOSE is set
|
|
13
|
+
*/
|
|
14
|
+
export const yesLog = tsaComposer()(
|
|
15
|
+
catcher(
|
|
16
|
+
(error) => {
|
|
17
|
+
console.error('yesLog error:', error);
|
|
18
|
+
},
|
|
19
|
+
function yesLog(msg: string) {
|
|
20
|
+
// process.stdout.write(`${msg}\r`); // touch process to avoid "The process is not running a TTY." error
|
|
21
|
+
if (!process.env.VERBOSE) return; // no-op if not verbose
|
|
22
|
+
if (initial) rmSync('./agent-yes.log'); // ignore error if file doesn't exist
|
|
23
|
+
initial = false;
|
|
24
|
+
appendFileSync('./agent-yes.log', `${msg}\n`);
|
|
25
|
+
},
|
|
26
|
+
),
|
|
27
|
+
);
|
package/ts/cli.test.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { exec } from 'node:child_process';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { readFile, unlink } from 'node:fs/promises';
|
|
4
|
-
import { execaCommand } from 'execa';
|
|
5
|
-
import { fromStdio } from 'from-node-stream';
|
|
6
|
-
import sflow from 'sflow';
|
|
7
|
-
import { beforeAll, describe, expect, it } from 'vitest';
|
|
8
|
-
import { IdleWaiter } from './idleWaiter';
|
|
9
|
-
import { sleepms } from './utils';
|
|
10
|
-
|
|
11
|
-
it('Write file with auto bypass prompts', async () => {
|
|
12
|
-
const flagFile = './.cache/flag.json';
|
|
13
|
-
await cleanup();
|
|
14
|
-
async function cleanup() {
|
|
15
|
-
await unlink(flagFile).catch(() => {});
|
|
16
|
-
await unlink('./cli-rendered.log').catch(() => {});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const p = exec(
|
|
20
|
-
`bunx tsx ./cli.ts --logFile=./cli-rendered.log --exit-on-idle=3s "just write {on: 1} into ./.cache/flag.json and wait"`,
|
|
21
|
-
);
|
|
22
|
-
const pExitCode = new Promise<number | null>((r) => p.once('exit', r));
|
|
23
|
-
|
|
24
|
-
const tr = new TransformStream<string, string>();
|
|
25
|
-
const w = tr.writable.getWriter();
|
|
26
|
-
|
|
27
|
-
const exit = async () =>
|
|
28
|
-
await sflow(['\r', '/exit', '\r', '\r'])
|
|
29
|
-
.forEach(async (e) => {
|
|
30
|
-
await sleepms(200);
|
|
31
|
-
await w.write(e);
|
|
32
|
-
})
|
|
33
|
-
.run();
|
|
34
|
-
|
|
35
|
-
// ping function to exit claude when idle
|
|
36
|
-
|
|
37
|
-
const idleWaiter = new IdleWaiter();
|
|
38
|
-
idleWaiter.wait(3000).then(() => exit());
|
|
39
|
-
|
|
40
|
-
const output = await sflow(tr.readable)
|
|
41
|
-
.by(fromStdio(p))
|
|
42
|
-
.log()
|
|
43
|
-
.forEach(() => idleWaiter.ping())
|
|
44
|
-
.text();
|
|
45
|
-
|
|
46
|
-
// expect the file exists
|
|
47
|
-
expect(existsSync(flagFile)).toBe(true);
|
|
48
|
-
// expect the output contains the file path
|
|
49
|
-
expect(output).toContain(flagFile);
|
|
50
|
-
|
|
51
|
-
// expect the file content to be 'on'
|
|
52
|
-
expect(await new Response(await readFile(flagFile)).json()).toEqual({
|
|
53
|
-
on: 1,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
expect(await pExitCode).toBe(0); // expect the process to exit successfully
|
|
57
|
-
expect(await readFile('./cli-rendered.log', 'utf8')).toBeTruthy();
|
|
58
|
-
|
|
59
|
-
// clean
|
|
60
|
-
await cleanup();
|
|
61
|
-
|
|
62
|
-
// it usually takes 13s to run (10s for claude to solve this problem, 3s for idle watcher to exit)
|
|
63
|
-
}, 30e3);
|