agent-sin 0.1.5 → 0.1.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.
- package/CHANGELOG.md +32 -0
- package/dist/cli/index.js +8 -7
- package/dist/core/ai-provider.js +8 -1
- package/dist/core/secrets.js +13 -8
- package/dist/core/transfer.js +49 -2
- package/dist/runtimes/codex-app-server.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,38 @@ See the [compatibility policy](https://agent.shingoirie.com/versioning) for deta
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## [0.1.9] — 2026-05-14
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- The `.env` permission warning ("permissions 666 ... are too open; recommend: chmod 600") no longer fires on Windows. POSIX-style mode bits are not meaningful on Windows (every file reports 0o666), so the check is skipped there.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## [0.1.8] — 2026-05-14
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Update notification on `agent-sin start` / `agent-sin chat` was being emitted *before* the ascii startup banner, so on small terminals it scrolled out of view. The notification now renders *after* the startup banner, with a blank line of separation, so it is always visible at the bottom of the welcome area.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## [0.1.7] — 2026-05-14
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- `agent-sin import` now rewrites absolute paths inside the restored `config.toml` (and legacy `config.yaml`) so the imported workspace points at the current machine's `~/.agent-sin` instead of the source machine's. Previously, restoring a backup on a different user account failed with `EACCES: permission denied, mkdir '/Users/<source>'`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## [0.1.6] — 2026-05-14
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- On Windows, launching the Codex CLI (and Claude Code CLI) failed with `spawn codex ENOENT` because Node's `spawn` cannot resolve the `.cmd` shim that npm-installed CLIs use on Windows. Both the one-shot CLI bridge and the long-running `codex app-server` now enable `shell: true` only on `win32`, so the shim is found correctly. POSIX paths still use direct exec.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
18
50
|
## [0.1.5] — 2026-05-14
|
|
19
51
|
|
|
20
52
|
### Changed
|
package/dist/cli/index.js
CHANGED
|
@@ -373,16 +373,10 @@ async function cmdRun(args) {
|
|
|
373
373
|
async function cmdChat(args) {
|
|
374
374
|
const config = await loadConfig();
|
|
375
375
|
scheduleUpdateCheck(config.workspace);
|
|
376
|
-
// Interactive CLI: always check the registry on startup so the user sees
|
|
377
|
-
// any new release immediately, not on the next session.
|
|
378
|
-
const startupBanner = await consumeUpdateBanner(config.workspace, { force: true });
|
|
379
|
-
if (startupBanner) {
|
|
380
|
-
console.log(startupBanner);
|
|
381
|
-
}
|
|
382
376
|
const history = [];
|
|
383
377
|
if (args.length > 0) {
|
|
384
378
|
const lines = await handleChatMessage(config, args.join(" "), history);
|
|
385
|
-
const banner = await consumeUpdateBanner(config.workspace);
|
|
379
|
+
const banner = await consumeUpdateBanner(config.workspace, { force: true });
|
|
386
380
|
if (banner) {
|
|
387
381
|
console.log(banner);
|
|
388
382
|
}
|
|
@@ -391,6 +385,9 @@ async function cmdChat(args) {
|
|
|
391
385
|
}
|
|
392
386
|
return 0;
|
|
393
387
|
}
|
|
388
|
+
// For the interactive session, always hit the registry on startup. Render the
|
|
389
|
+
// banner *after* the ascii banner so it stays visible on small terminals.
|
|
390
|
+
const startupUpdateBanner = await consumeUpdateBanner(config.workspace, { force: true });
|
|
394
391
|
await warnIfSchedulesNeedService(config);
|
|
395
392
|
const intentRuntime = {
|
|
396
393
|
pending: null,
|
|
@@ -420,6 +417,10 @@ async function cmdChat(args) {
|
|
|
420
417
|
console.log(l("agent-sin chat. /help / /reset / /exit (Tab completion)", "agent-sin chat. /help / /reset / /exit (Tabで補完)"));
|
|
421
418
|
console.log(l("mode: chat | build/edit mode is suggested automatically when useful", "mode: chat | 必要に応じてビルド/編集モードに自動で切替提案します"));
|
|
422
419
|
}
|
|
420
|
+
if (startupUpdateBanner) {
|
|
421
|
+
console.log("");
|
|
422
|
+
console.log(uiActive() ? formatChatLine(startupUpdateBanner) : startupUpdateBanner);
|
|
423
|
+
}
|
|
423
424
|
while (true) {
|
|
424
425
|
let raw;
|
|
425
426
|
const frameTop = renderInputFrameTop();
|
package/dist/core/ai-provider.js
CHANGED
|
@@ -643,7 +643,14 @@ function splitExtraArgs(value) {
|
|
|
643
643
|
}
|
|
644
644
|
async function spawnCli(bin, args, modelId, provider, onProgress, cwd) {
|
|
645
645
|
return new Promise((resolve, reject) => {
|
|
646
|
-
|
|
646
|
+
// Windows wraps CLI tools as .cmd / .bat shims (codex.cmd, claude.cmd).
|
|
647
|
+
// Node's spawn cannot exec those without going through a shell, so we
|
|
648
|
+
// enable shell only on win32. Posix paths keep direct exec for safety.
|
|
649
|
+
const child = spawn(bin, args, {
|
|
650
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
651
|
+
cwd,
|
|
652
|
+
shell: process.platform === "win32",
|
|
653
|
+
});
|
|
647
654
|
const stdout = [];
|
|
648
655
|
const stderr = [];
|
|
649
656
|
let stderrLine = "";
|
package/dist/core/secrets.js
CHANGED
|
@@ -34,15 +34,20 @@ export async function loadDotenv(workspace = defaultWorkspace()) {
|
|
|
34
34
|
return { loaded: false, path: file, vars_set: 0 };
|
|
35
35
|
}
|
|
36
36
|
let permissionWarning;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
// POSIX-style mode bits do not have meaningful semantics on Windows, where
|
|
38
|
+
// every file reports 0o666 by default. Skip the check there to avoid a
|
|
39
|
+
// false-positive warning on every CLI start.
|
|
40
|
+
if (process.platform !== "win32") {
|
|
41
|
+
try {
|
|
42
|
+
const info = await stat(file);
|
|
43
|
+
const mode = info.mode & 0o777;
|
|
44
|
+
if ((mode & 0o077) !== 0) {
|
|
45
|
+
permissionWarning = `permissions ${mode.toString(8).padStart(3, "0")} on ${file} are too open; recommend: chmod 600 ${file}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Ignore stat failures; the file was readable above.
|
|
42
50
|
}
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// Ignore stat failures; the file was readable above.
|
|
46
51
|
}
|
|
47
52
|
let varsSet = 0;
|
|
48
53
|
for (const line of raw.split(/\r?\n/)) {
|
package/dist/core/transfer.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { copyFile, lstat, mkdir, mkdtemp, readdir, rename, rm, stat } from "node:fs/promises";
|
|
2
|
+
import { copyFile, lstat, mkdir, mkdtemp, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { defaultWorkspace } from "./config.js";
|
|
5
|
+
import { configPath, defaultWorkspace, legacyConfigPath, normalizeConfig, parseTomlConfigWithLegacy, writeConfig, } from "./config.js";
|
|
6
|
+
import YAML from "yaml";
|
|
6
7
|
import { l } from "./i18n.js";
|
|
7
8
|
const DEFAULT_INCLUDE = [
|
|
8
9
|
".env",
|
|
@@ -90,12 +91,58 @@ export async function importWorkspace(options) {
|
|
|
90
91
|
}
|
|
91
92
|
await mkdir(workspace, { recursive: true });
|
|
92
93
|
await copySafeTree(tempRoot, workspace);
|
|
94
|
+
// Backups carry the absolute paths of the source machine. Rewrite them so
|
|
95
|
+
// the imported workspace points at this machine's locations.
|
|
96
|
+
await rewriteImportedConfigPaths(workspace);
|
|
93
97
|
return { workspace, archivePath, entries, backupPath, dryRun: false };
|
|
94
98
|
}
|
|
95
99
|
finally {
|
|
96
100
|
await rm(tempRoot, { recursive: true, force: true });
|
|
97
101
|
}
|
|
98
102
|
}
|
|
103
|
+
async function rewriteImportedConfigPaths(workspace) {
|
|
104
|
+
const tomlFile = configPath(workspace);
|
|
105
|
+
if (await pathExists(tomlFile)) {
|
|
106
|
+
try {
|
|
107
|
+
const raw = await readFile(tomlFile, "utf8");
|
|
108
|
+
const parsed = parseTomlConfigWithLegacy(raw);
|
|
109
|
+
const rewritten = normalizeConfig({
|
|
110
|
+
...parsed.config,
|
|
111
|
+
workspace,
|
|
112
|
+
notes_dir: path.join(workspace, "notes"),
|
|
113
|
+
skills_dir: path.join(workspace, "skills"),
|
|
114
|
+
memory_dir: path.join(workspace, "memory"),
|
|
115
|
+
index_dir: path.join(workspace, "index"),
|
|
116
|
+
logs_dir: path.join(workspace, "logs"),
|
|
117
|
+
});
|
|
118
|
+
await writeConfig(tomlFile, rewritten);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Silently skip when the imported config.toml cannot be parsed; the
|
|
122
|
+
// user can still manually edit it.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const yamlFile = legacyConfigPath(workspace);
|
|
126
|
+
if (await pathExists(yamlFile)) {
|
|
127
|
+
try {
|
|
128
|
+
const raw = await readFile(yamlFile, "utf8");
|
|
129
|
+
const parsed = YAML.parse(raw) || {};
|
|
130
|
+
const rewritten = {
|
|
131
|
+
...parsed,
|
|
132
|
+
workspace,
|
|
133
|
+
notes_dir: path.join(workspace, "notes"),
|
|
134
|
+
skills_dir: path.join(workspace, "skills"),
|
|
135
|
+
memory_dir: path.join(workspace, "memory"),
|
|
136
|
+
index_dir: path.join(workspace, "index"),
|
|
137
|
+
logs_dir: path.join(workspace, "logs"),
|
|
138
|
+
};
|
|
139
|
+
await writeFile(yamlFile, YAML.stringify(rewritten), "utf8");
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// ignore - legacy yaml is best-effort
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
99
146
|
async function backupExistingWorkspace(workspace) {
|
|
100
147
|
const ts = formatTimestamp(new Date());
|
|
101
148
|
const backupPath = `${workspace}.bak-${ts}`;
|
|
@@ -104,8 +104,11 @@ export class CodexAppServerSession {
|
|
|
104
104
|
await this.starting;
|
|
105
105
|
}
|
|
106
106
|
async start() {
|
|
107
|
+
// Windows wraps the codex CLI as a .cmd shim; Node's spawn cannot exec
|
|
108
|
+
// those without a shell, so we enable shell only on win32.
|
|
107
109
|
const child = spawn(this.options.bin, this.options.args, {
|
|
108
110
|
stdio: ["pipe", "pipe", "pipe"],
|
|
111
|
+
shell: process.platform === "win32",
|
|
109
112
|
});
|
|
110
113
|
this.child = child;
|
|
111
114
|
this.exitReason = null;
|