@phnx-labs/agents-cli 1.20.4 → 1.20.5
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 +19 -0
- package/README.md +48 -17
- package/dist/commands/cli.js +1 -1
- package/dist/commands/cloud.js +1 -1
- package/dist/commands/commands.js +2 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/exec.js +52 -16
- package/dist/commands/hooks.js +6 -6
- package/dist/commands/inspect.d.ts +26 -0
- package/dist/commands/inspect.js +590 -0
- package/dist/commands/mcp.js +17 -16
- package/dist/commands/models.js +1 -1
- package/dist/commands/packages.js +6 -4
- package/dist/commands/permissions.js +13 -12
- package/dist/commands/plugins.d.ts +13 -0
- package/dist/commands/plugins.js +100 -11
- package/dist/commands/prune.js +3 -2
- package/dist/commands/pull.d.ts +12 -5
- package/dist/commands/pull.js +26 -422
- package/dist/commands/push.d.ts +14 -0
- package/dist/commands/push.js +30 -0
- package/dist/commands/repo.d.ts +1 -1
- package/dist/commands/repo.js +155 -112
- package/dist/commands/resource-view.d.ts +2 -0
- package/dist/commands/resource-view.js +12 -3
- package/dist/commands/routines.js +32 -7
- package/dist/commands/rules.js +1 -1
- package/dist/commands/sessions.js +1 -0
- package/dist/commands/setup.d.ts +3 -3
- package/dist/commands/setup.js +15 -15
- package/dist/commands/skills.js +6 -5
- package/dist/commands/subagents.js +5 -4
- package/dist/commands/sync.d.ts +18 -5
- package/dist/commands/sync.js +251 -65
- package/dist/commands/teams.js +1 -0
- package/dist/commands/tmux.d.ts +25 -0
- package/dist/commands/tmux.js +415 -0
- package/dist/commands/trash.d.ts +2 -2
- package/dist/commands/trash.js +1 -1
- package/dist/commands/versions.js +2 -2
- package/dist/commands/view.js +9 -4
- package/dist/commands/workflows.js +4 -3
- package/dist/commands/worktree.d.ts +4 -5
- package/dist/commands/worktree.js +4 -4
- package/dist/index.js +68 -20
- package/dist/lib/agents.d.ts +19 -10
- package/dist/lib/agents.js +79 -25
- package/dist/lib/auto-pull-worker.d.ts +1 -1
- package/dist/lib/auto-pull-worker.js +2 -2
- package/dist/lib/auto-pull.d.ts +1 -1
- package/dist/lib/auto-pull.js +1 -1
- package/dist/lib/beta.d.ts +1 -1
- package/dist/lib/beta.js +1 -1
- package/dist/lib/capabilities.js +2 -0
- package/dist/lib/commands.d.ts +28 -1
- package/dist/lib/commands.js +125 -20
- package/dist/lib/doctor-diff.js +2 -2
- package/dist/lib/exec.d.ts +14 -0
- package/dist/lib/exec.js +39 -5
- package/dist/lib/fuzzy.d.ts +12 -2
- package/dist/lib/fuzzy.js +29 -4
- package/dist/lib/git.js +8 -1
- package/dist/lib/hooks.d.ts +2 -2
- package/dist/lib/hooks.js +97 -10
- package/dist/lib/mcp.js +32 -2
- package/dist/lib/migrate.d.ts +51 -0
- package/dist/lib/migrate.js +227 -1
- package/dist/lib/models.js +62 -15
- package/dist/lib/permissions.d.ts +36 -2
- package/dist/lib/permissions.js +217 -7
- package/dist/lib/plugin-marketplace.d.ts +98 -40
- package/dist/lib/plugin-marketplace.js +196 -93
- package/dist/lib/plugins.d.ts +21 -4
- package/dist/lib/plugins.js +130 -49
- package/dist/lib/profiles-presets.js +12 -12
- package/dist/lib/project-launch.d.ts +65 -0
- package/dist/lib/project-launch.js +367 -0
- package/dist/lib/pty-client.js +1 -1
- package/dist/lib/pty-server.d.ts +1 -1
- package/dist/lib/pty-server.js +1 -1
- package/dist/lib/refresh.d.ts +26 -0
- package/dist/lib/refresh.js +315 -0
- package/dist/lib/resource-patterns.d.ts +1 -1
- package/dist/lib/resource-patterns.js +1 -1
- package/dist/lib/resources/commands.js +2 -2
- package/dist/lib/resources/hooks.d.ts +1 -1
- package/dist/lib/resources/hooks.js +1 -1
- package/dist/lib/resources/mcp.d.ts +1 -1
- package/dist/lib/resources/mcp.js +5 -6
- package/dist/lib/resources/permissions.js +5 -2
- package/dist/lib/resources/rules.js +3 -2
- package/dist/lib/resources/skills.js +3 -2
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.js +2 -2
- package/dist/lib/rotate.d.ts +1 -1
- package/dist/lib/rotate.js +1 -1
- package/dist/lib/routines.d.ts +16 -4
- package/dist/lib/routines.js +67 -17
- package/dist/lib/rules/compile.js +22 -10
- package/dist/lib/rules/rules.js +3 -3
- package/dist/lib/runner.js +16 -3
- package/dist/lib/scheduler.js +15 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +9 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/secrets/linux.d.ts +44 -9
- package/dist/lib/secrets/linux.js +302 -48
- package/dist/lib/session/db.js +15 -2
- package/dist/lib/session/discover.js +118 -3
- package/dist/lib/session/parse.js +3 -0
- package/dist/lib/session/types.d.ts +1 -1
- package/dist/lib/session/types.js +1 -1
- package/dist/lib/shims.d.ts +10 -9
- package/dist/lib/shims.js +101 -50
- package/dist/lib/skills.d.ts +1 -1
- package/dist/lib/skills.js +10 -9
- package/dist/lib/staleness/detectors/commands.d.ts +3 -0
- package/dist/lib/staleness/detectors/commands.js +46 -0
- package/dist/lib/staleness/detectors/hooks.d.ts +3 -0
- package/dist/lib/staleness/detectors/hooks.js +44 -0
- package/dist/lib/staleness/detectors/mcp.d.ts +3 -0
- package/dist/lib/staleness/detectors/mcp.js +31 -0
- package/dist/lib/staleness/detectors/permissions.d.ts +3 -0
- package/dist/lib/staleness/detectors/permissions.js +201 -0
- package/dist/lib/staleness/detectors/plugins.d.ts +8 -0
- package/dist/lib/staleness/detectors/plugins.js +23 -0
- package/dist/lib/staleness/detectors/rules.d.ts +3 -0
- package/dist/lib/staleness/detectors/rules.js +34 -0
- package/dist/lib/staleness/detectors/skills.d.ts +3 -0
- package/dist/lib/staleness/detectors/skills.js +71 -0
- package/dist/lib/staleness/detectors/subagents.d.ts +3 -0
- package/dist/lib/staleness/detectors/subagents.js +50 -0
- package/dist/lib/staleness/detectors/types.d.ts +22 -0
- package/dist/lib/staleness/detectors/types.js +1 -0
- package/dist/lib/staleness/detectors/workflows.d.ts +3 -0
- package/dist/lib/staleness/detectors/workflows.js +28 -0
- package/dist/lib/staleness/registry.d.ts +26 -0
- package/dist/lib/staleness/registry.js +123 -0
- package/dist/lib/staleness/writers/commands.d.ts +3 -0
- package/dist/lib/staleness/writers/commands.js +111 -0
- package/dist/lib/staleness/writers/hooks.d.ts +3 -0
- package/dist/lib/staleness/writers/hooks.js +47 -0
- package/dist/lib/staleness/writers/kinds.d.ts +10 -0
- package/dist/lib/staleness/writers/kinds.js +15 -0
- package/dist/lib/staleness/writers/lazy-map.d.ts +13 -0
- package/dist/lib/staleness/writers/lazy-map.js +19 -0
- package/dist/lib/staleness/writers/mcp.d.ts +10 -0
- package/dist/lib/staleness/writers/mcp.js +19 -0
- package/dist/lib/staleness/writers/permissions.d.ts +13 -0
- package/dist/lib/staleness/writers/permissions.js +26 -0
- package/dist/lib/staleness/writers/plugins.d.ts +7 -0
- package/dist/lib/staleness/writers/plugins.js +31 -0
- package/dist/lib/staleness/writers/rules.d.ts +7 -0
- package/dist/lib/staleness/writers/rules.js +55 -0
- package/dist/lib/staleness/writers/skills.d.ts +3 -0
- package/dist/lib/staleness/writers/skills.js +81 -0
- package/dist/lib/staleness/writers/sources.d.ts +16 -0
- package/dist/lib/staleness/writers/sources.js +72 -0
- package/dist/lib/staleness/writers/subagents.d.ts +3 -0
- package/dist/lib/staleness/writers/subagents.js +53 -0
- package/dist/lib/staleness/writers/types.d.ts +36 -0
- package/dist/lib/staleness/writers/types.js +1 -0
- package/dist/lib/staleness/writers/workflows.d.ts +7 -0
- package/dist/lib/staleness/writers/workflows.js +31 -0
- package/dist/lib/state.d.ts +34 -11
- package/dist/lib/state.js +58 -13
- package/dist/lib/subagents.d.ts +0 -2
- package/dist/lib/subagents.js +6 -6
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/tmux/binary.d.ts +67 -0
- package/dist/lib/tmux/binary.js +141 -0
- package/dist/lib/tmux/index.d.ts +8 -0
- package/dist/lib/tmux/index.js +8 -0
- package/dist/lib/tmux/paths.d.ts +17 -0
- package/dist/lib/tmux/paths.js +30 -0
- package/dist/lib/tmux/session.d.ts +122 -0
- package/dist/lib/tmux/session.js +305 -0
- package/dist/lib/types.d.ts +58 -7
- package/dist/lib/types.js +1 -1
- package/dist/lib/usage.js +1 -1
- package/dist/lib/versions.d.ts +4 -4
- package/dist/lib/versions.js +135 -493
- package/dist/lib/workflows.d.ts +2 -4
- package/dist/lib/workflows.js +3 -4
- package/package.json +2 -2
- package/scripts/postinstall.js +16 -63
- package/dist/commands/status.d.ts +0 -9
- package/dist/commands/status.js +0 -25
package/dist/lib/routines.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as fs from 'fs';
|
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as yaml from 'yaml';
|
|
12
12
|
import { Cron } from 'croner';
|
|
13
|
-
import { getRoutinesDir, getRunsDir, ensureAgentsDir } from './state.js';
|
|
13
|
+
import { getRoutinesDir, getRunsDir, ensureAgentsDir, getProjectRoutinesDir } from './state.js';
|
|
14
14
|
import { safeJoin } from './paths.js';
|
|
15
15
|
import { ALL_AGENT_IDS } from './agents.js';
|
|
16
16
|
/** Default values applied to every job config when fields are omitted. */
|
|
@@ -20,29 +20,59 @@ const JOB_DEFAULTS = {
|
|
|
20
20
|
timeout: '10m',
|
|
21
21
|
enabled: true,
|
|
22
22
|
};
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* List all job configs, scanning project > user routine dirs.
|
|
25
|
+
* Project routines (`<project>/.agents/routines/`) shadow user routines of the
|
|
26
|
+
* same name. Project discovery is opt-in via `cwd`; the daemon (which calls
|
|
27
|
+
* `listJobs()` with no argument) only sees user routines.
|
|
28
|
+
*/
|
|
29
|
+
export function listJobs(cwd) {
|
|
25
30
|
ensureAgentsDir();
|
|
26
|
-
const
|
|
27
|
-
if (!fs.existsSync(jobsDir))
|
|
28
|
-
return [];
|
|
29
|
-
const files = fs.readdirSync(jobsDir).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
31
|
+
const seen = new Set();
|
|
30
32
|
const jobs = [];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const dirs = [];
|
|
34
|
+
if (cwd) {
|
|
35
|
+
const projectDir = getProjectRoutinesDir(cwd);
|
|
36
|
+
if (projectDir)
|
|
37
|
+
dirs.push(projectDir);
|
|
38
|
+
}
|
|
39
|
+
dirs.push(getRoutinesDir());
|
|
40
|
+
for (const dir of dirs) {
|
|
41
|
+
if (!fs.existsSync(dir))
|
|
42
|
+
continue;
|
|
43
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
const job = readJobFile(path.join(dir, file));
|
|
46
|
+
if (!job)
|
|
47
|
+
continue;
|
|
48
|
+
if (seen.has(job.name))
|
|
49
|
+
continue;
|
|
50
|
+
seen.add(job.name);
|
|
34
51
|
jobs.push(job);
|
|
52
|
+
}
|
|
35
53
|
}
|
|
36
54
|
return jobs;
|
|
37
55
|
}
|
|
38
|
-
/**
|
|
39
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Read a single job config by name, checking project > user.
|
|
58
|
+
* Project discovery is opt-in via `cwd`; daemon callers pass no argument and
|
|
59
|
+
* only resolve user routines.
|
|
60
|
+
*/
|
|
61
|
+
export function readJob(name, cwd) {
|
|
40
62
|
ensureAgentsDir();
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
|
|
63
|
+
const dirs = [];
|
|
64
|
+
if (cwd) {
|
|
65
|
+
const projectDir = getProjectRoutinesDir(cwd);
|
|
66
|
+
if (projectDir)
|
|
67
|
+
dirs.push(projectDir);
|
|
68
|
+
}
|
|
69
|
+
dirs.push(getRoutinesDir());
|
|
70
|
+
for (const dir of dirs) {
|
|
71
|
+
for (const ext of ['.yml', '.yaml']) {
|
|
72
|
+
const filePath = safeJoin(dir, name + ext);
|
|
73
|
+
if (fs.existsSync(filePath)) {
|
|
74
|
+
return readJobFile(filePath);
|
|
75
|
+
}
|
|
46
76
|
}
|
|
47
77
|
}
|
|
48
78
|
return null;
|
|
@@ -147,8 +177,28 @@ export function validateJob(config) {
|
|
|
147
177
|
if (config.timeout && !parseTimeout(config.timeout)) {
|
|
148
178
|
errors.push('timeout must be like 10m, 2h, 3d, 1w (max 1w)');
|
|
149
179
|
}
|
|
180
|
+
if (config.endAt !== undefined) {
|
|
181
|
+
if (typeof config.endAt !== 'string' || !isParseableDate(config.endAt)) {
|
|
182
|
+
errors.push('endAt must be a parseable ISO 8601 / RFC3339 timestamp (e.g., 2026-12-31T23:59:00Z)');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
150
185
|
return errors;
|
|
151
186
|
}
|
|
187
|
+
function isParseableDate(value) {
|
|
188
|
+
if (!value.trim())
|
|
189
|
+
return false;
|
|
190
|
+
const ts = Date.parse(value);
|
|
191
|
+
return Number.isFinite(ts);
|
|
192
|
+
}
|
|
193
|
+
/** True when a job's endAt has already elapsed. False when endAt is unset or in the future. */
|
|
194
|
+
export function isPastEndAt(config, now = new Date()) {
|
|
195
|
+
if (!config.endAt)
|
|
196
|
+
return false;
|
|
197
|
+
const end = Date.parse(config.endAt);
|
|
198
|
+
if (!Number.isFinite(end))
|
|
199
|
+
return false;
|
|
200
|
+
return now.getTime() >= end;
|
|
201
|
+
}
|
|
152
202
|
/** Expand built-in and user-defined template variables in a job's prompt string. */
|
|
153
203
|
export function resolveJobPrompt(config) {
|
|
154
204
|
const now = new Date();
|
|
@@ -10,8 +10,8 @@ import * as fs from 'fs';
|
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as os from 'os';
|
|
12
12
|
import * as crypto from 'crypto';
|
|
13
|
-
import { AGENTS } from '../agents.js';
|
|
14
|
-
import {
|
|
13
|
+
import { AGENTS, agentConfigDirName } from '../agents.js';
|
|
14
|
+
import { getVersionsDir } from '../state.js';
|
|
15
15
|
import { composeRules, composeRulesFromState } from './compose.js';
|
|
16
16
|
// Match `@path` preceded by start-of-string or whitespace. This avoids
|
|
17
17
|
// matching emails ("foo@bar.com") and the middle of words. The leading
|
|
@@ -97,7 +97,7 @@ export function supportsRulesImports(agentId) {
|
|
|
97
97
|
function getCompiledRulesPath(agentId, version) {
|
|
98
98
|
const agentConfig = AGENTS[agentId];
|
|
99
99
|
const versionHome = path.join(getVersionsDir(), agentId, version, 'home');
|
|
100
|
-
return path.join(versionHome,
|
|
100
|
+
return path.join(versionHome, agentConfigDirName(agentId), agentConfig.instructionsFile);
|
|
101
101
|
}
|
|
102
102
|
function getManifestPath(compiledPath) {
|
|
103
103
|
return compiledPath + '.manifest.json';
|
|
@@ -151,14 +151,24 @@ export function compileRulesForAgent(agentId, version) {
|
|
|
151
151
|
if (supportsRulesImports(agentId)) {
|
|
152
152
|
return { compiled: false, compiledPath: '', sources: 0 };
|
|
153
153
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
// Route through the layered composer (project > user > extras > system).
|
|
155
|
+
// The previous implementation read only `<systemRules>/AGENTS.md` and
|
|
156
|
+
// inlined its @-imports — that dropped user/extras/project subrules
|
|
157
|
+
// entirely for @-import-incapable agents (Cursor, older Codex), so
|
|
158
|
+
// updates to ~/.agents/rules/subrules/ never reached the version home.
|
|
159
|
+
// composeRulesFromState already returns the concatenated content with
|
|
160
|
+
// every fragment resolved across layers; we just need to record the
|
|
161
|
+
// composed source list for staleness detection.
|
|
162
|
+
let composed;
|
|
163
|
+
try {
|
|
164
|
+
composed = composeRulesFromState({ preset: undefined });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// No rules.yaml in any layer, or the default preset is missing — leave
|
|
168
|
+
// the version home untouched (matches the previous file-missing branch).
|
|
157
169
|
return { compiled: false, compiledPath: '', sources: 0 };
|
|
158
170
|
}
|
|
159
|
-
const
|
|
160
|
-
const { content, sources } = resolveImports(rootContent, rulesDir);
|
|
161
|
-
const newContent = COMPILED_HEADER + content;
|
|
171
|
+
const newContent = COMPILED_HEADER + composed.content;
|
|
162
172
|
const compiledPath = getCompiledRulesPath(agentId, version);
|
|
163
173
|
fs.mkdirSync(path.dirname(compiledPath), { recursive: true });
|
|
164
174
|
const existing = fs.existsSync(compiledPath) ? fs.readFileSync(compiledPath, 'utf8') : null;
|
|
@@ -166,7 +176,9 @@ export function compileRulesForAgent(agentId, version) {
|
|
|
166
176
|
return { compiled: false, compiledPath, sources: 0 };
|
|
167
177
|
}
|
|
168
178
|
fs.writeFileSync(compiledPath, newContent);
|
|
169
|
-
|
|
179
|
+
// Track every concrete subrule file the composer included as a source for
|
|
180
|
+
// staleness. composeRulesFromState exposes sourcePath on each ComposedSubrule.
|
|
181
|
+
const allSources = composed.subrules.map(s => s.sourcePath);
|
|
170
182
|
const manifest = {
|
|
171
183
|
compiledAt: new Date().toISOString(),
|
|
172
184
|
sources: allSources.map(p => {
|
package/dist/lib/rules/rules.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
|
-
import { AGENTS, ALL_AGENT_IDS } from '../agents.js';
|
|
11
|
+
import { AGENTS, ALL_AGENT_IDS, agentConfigDirName } from '../agents.js';
|
|
12
12
|
import { getResolvedRulesDir, getUserRulesDir, getProjectAgentsDir } from '../state.js';
|
|
13
13
|
import { getEffectiveHome } from '../versions.js';
|
|
14
14
|
/**
|
|
@@ -65,7 +65,7 @@ function normalizeContent(content) {
|
|
|
65
65
|
*/
|
|
66
66
|
function getUserConfigDir(agentId) {
|
|
67
67
|
const home = getEffectiveHome(agentId);
|
|
68
|
-
return path.join(home,
|
|
68
|
+
return path.join(home, agentConfigDirName(agentId));
|
|
69
69
|
}
|
|
70
70
|
export function getInstructionsPath(agentId, scope, cwd = process.cwd()) {
|
|
71
71
|
const agent = AGENTS[agentId];
|
|
@@ -211,7 +211,7 @@ export function listInstalledInstructionsWithScope(agentId, cwd = process.cwd(),
|
|
|
211
211
|
const agent = AGENTS[agentId];
|
|
212
212
|
// User-scoped instructions (version-aware when home is provided)
|
|
213
213
|
const home = options?.home || getEffectiveHome(agentId);
|
|
214
|
-
const userConfigDir = path.join(home,
|
|
214
|
+
const userConfigDir = path.join(home, agentConfigDirName(agentId));
|
|
215
215
|
const userPath = path.join(userConfigDir, agent.instructionsFile);
|
|
216
216
|
results.push({
|
|
217
217
|
agentId,
|
package/dist/lib/runner.js
CHANGED
|
@@ -21,6 +21,7 @@ const AGENT_COMMANDS = {
|
|
|
21
21
|
claude: ['claude', '-p', '--verbose', '{prompt}', '--output-format', 'stream-json', '--permission-mode', 'plan'],
|
|
22
22
|
codex: ['codex', 'exec', '--sandbox', 'workspace-write', '{prompt}', '--json'],
|
|
23
23
|
gemini: ['gemini', '{prompt}', '--output-format', 'stream-json'],
|
|
24
|
+
kimi: ['kimi', '--prompt', '{prompt}', '--output-format', 'stream-json'],
|
|
24
25
|
};
|
|
25
26
|
/** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
|
|
26
27
|
export function buildJobCommand(config, resolvedPrompt) {
|
|
@@ -72,14 +73,14 @@ export function buildJobCommand(config, resolvedPrompt) {
|
|
|
72
73
|
}
|
|
73
74
|
if (config.agent === 'codex') {
|
|
74
75
|
if (mode === 'edit') {
|
|
75
|
-
cmd.push('--
|
|
76
|
+
cmd.push('--dangerously-bypass-approvals-and-sandbox');
|
|
76
77
|
}
|
|
77
78
|
else if (mode === 'skip') {
|
|
78
|
-
// Remove sandbox restriction, just --
|
|
79
|
+
// Remove sandbox restriction, just --dangerously-bypass-approvals-and-sandbox
|
|
79
80
|
const sbIndex = cmd.indexOf('--sandbox');
|
|
80
81
|
if (sbIndex !== -1)
|
|
81
82
|
cmd.splice(sbIndex, 2);
|
|
82
|
-
cmd.push('--
|
|
83
|
+
cmd.push('--dangerously-bypass-approvals-and-sandbox');
|
|
83
84
|
}
|
|
84
85
|
appendModelAndReasoning(cmd, config);
|
|
85
86
|
}
|
|
@@ -92,6 +93,18 @@ export function buildJobCommand(config, resolvedPrompt) {
|
|
|
92
93
|
}
|
|
93
94
|
appendModelAndReasoning(cmd, config);
|
|
94
95
|
}
|
|
96
|
+
if (config.agent === 'kimi') {
|
|
97
|
+
if (mode === 'plan') {
|
|
98
|
+
cmd.push('--plan');
|
|
99
|
+
}
|
|
100
|
+
else if (mode === 'auto') {
|
|
101
|
+
cmd.push('--auto');
|
|
102
|
+
}
|
|
103
|
+
else if (mode === 'skip') {
|
|
104
|
+
cmd.push('--yolo');
|
|
105
|
+
}
|
|
106
|
+
appendModelAndReasoning(cmd, config);
|
|
107
|
+
}
|
|
95
108
|
return cmd;
|
|
96
109
|
}
|
|
97
110
|
/**
|
package/dist/lib/scheduler.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* on startup and reloads them on SIGHUP.
|
|
7
7
|
*/
|
|
8
8
|
import { Cron } from 'croner';
|
|
9
|
-
import { listJobs, deleteJob } from './routines.js';
|
|
9
|
+
import { listJobs, deleteJob, isPastEndAt, setJobEnabled } from './routines.js';
|
|
10
10
|
/** In-memory cron scheduler that triggers a callback when jobs fire. */
|
|
11
11
|
export class JobScheduler {
|
|
12
12
|
jobs = new Map();
|
|
@@ -32,6 +32,20 @@ export class JobScheduler {
|
|
|
32
32
|
if (config.timezone)
|
|
33
33
|
cronOptions.timezone = config.timezone;
|
|
34
34
|
const cron = new Cron(config.schedule, cronOptions, async () => {
|
|
35
|
+
// endAt: once the configured end time has passed, auto-disable and stop
|
|
36
|
+
// firing. We persist enabled=false to disk so the next daemon reload
|
|
37
|
+
// doesn't re-schedule, and unschedule in-memory so this cron stops.
|
|
38
|
+
if (isPastEndAt(config)) {
|
|
39
|
+
this.unschedule(config.name);
|
|
40
|
+
try {
|
|
41
|
+
setJobEnabled(config.name, false);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
console.error(`Job '${config.name}' endAt auto-disable failed:`, err.message);
|
|
45
|
+
}
|
|
46
|
+
console.log(`Job '${config.name}' reached endAt (${config.endAt}); auto-disabled.`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
35
49
|
try {
|
|
36
50
|
await this.onTrigger(config);
|
|
37
51
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -5,7 +5,15 @@
|
|
|
5
5
|
<key>files</key>
|
|
6
6
|
<dict/>
|
|
7
7
|
<key>files2</key>
|
|
8
|
-
<dict
|
|
8
|
+
<dict>
|
|
9
|
+
<key>embedded.provisionprofile</key>
|
|
10
|
+
<dict>
|
|
11
|
+
<key>hash2</key>
|
|
12
|
+
<data>
|
|
13
|
+
2vfA/eR3dTYgNc/fXhdADUPkp5tRIepPzE3FCLfDx4w=
|
|
14
|
+
</data>
|
|
15
|
+
</dict>
|
|
16
|
+
</dict>
|
|
9
17
|
<key>rules</key>
|
|
10
18
|
<dict>
|
|
11
19
|
<key>^Resources/</key>
|
|
@@ -1,19 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Linux secret storage via libsecret (GNOME Keyring / Secret Service API).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* On Ubuntu: apt install libsecret-tools
|
|
4
|
+
* Primary backend: `secret-tool` CLI (libsecret-tools package).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
6
|
+
* Headless fallback: when the default Secret Service collection is locked
|
|
7
|
+
* (common on server-class Linux — no graphical login means the keyring
|
|
8
|
+
* passphrase never enters the daemon, so `secret-tool store` fails with
|
|
9
|
+
* "Cannot create an item in a locked collection"), we transparently switch
|
|
10
|
+
* to a file-based AES-256-GCM encrypted store under
|
|
11
|
+
* `~/.agents/.cache/secrets/`. The encryption key is scrypt-derived from a
|
|
12
|
+
* passphrase read from `AGENTS_SECRETS_PASSPHRASE` (preferred) or a TTY
|
|
13
|
+
* prompt. The decision is cached per process; one stderr line is emitted
|
|
14
|
+
* the first time the fallback activates.
|
|
15
|
+
*
|
|
16
|
+
* Secrets stored via secret-tool use:
|
|
8
17
|
* service = "agents-cli"
|
|
9
18
|
* account = username
|
|
10
|
-
* item
|
|
19
|
+
* item = the secret identifier
|
|
20
|
+
*
|
|
21
|
+
* File-fallback layout: one `<item>.enc` JSON file per item, mode 0600.
|
|
11
22
|
*/
|
|
12
23
|
import type { KeychainBackend } from './index.js';
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
/** Encrypted-file on-disk shape. Exported for tests. */
|
|
25
|
+
export interface EncFile {
|
|
26
|
+
salt: string;
|
|
27
|
+
iv: string;
|
|
28
|
+
authTag: string;
|
|
29
|
+
ciphertext: string;
|
|
30
|
+
}
|
|
31
|
+
/** Encrypt plaintext under a passphrase using AES-256-GCM with a random
|
|
32
|
+
* scrypt salt and a random 96-bit IV. Exported for tests. */
|
|
33
|
+
export declare function encryptForFallback(plaintext: string, passphrase: string): EncFile;
|
|
34
|
+
/** Decrypt an EncFile under a passphrase. Throws on wrong key or tampered
|
|
35
|
+
* ciphertext (auth-tag mismatch). Exported for tests. */
|
|
36
|
+
export declare function decryptForFallback(enc: EncFile, passphrase: string): string;
|
|
37
|
+
/** File-only KeychainBackend (exported for tests; the public surface uses
|
|
38
|
+
* the secret-tool-with-fallback `linuxBackend` below). */
|
|
39
|
+
export declare const fileBackend: KeychainBackend;
|
|
40
|
+
/** secret-tool lookup attributes:
|
|
41
|
+
* service=agents-cli account=<user> item=<itemName> */
|
|
17
42
|
export declare function hasSecretToolToken(item: string): boolean;
|
|
18
43
|
export declare function getSecretToolToken(item: string): string;
|
|
19
44
|
export declare function setSecretToolToken(item: string, value: string): void;
|
|
@@ -23,5 +48,15 @@ export declare function deleteSecretToolToken(item: string): boolean;
|
|
|
23
48
|
* so we use secret-tool search which outputs in a specific format.
|
|
24
49
|
*/
|
|
25
50
|
export declare function listSecretToolItems(prefix: string): string[];
|
|
26
|
-
/** KeychainBackend implementation for Linux
|
|
51
|
+
/** KeychainBackend implementation for Linux. Routes through secret-tool
|
|
52
|
+
* with a transparent encrypted-file fallback when the default Secret
|
|
53
|
+
* Service collection is locked (or libsecret-tools is not installed but
|
|
54
|
+
* AGENTS_SECRETS_PASSPHRASE is set). */
|
|
27
55
|
export declare const linuxBackend: KeychainBackend;
|
|
56
|
+
/** Test-only: reset module state so independent test cases don't bleed
|
|
57
|
+
* passphrase / fallback decisions across each other. */
|
|
58
|
+
export declare function _resetForTest(opts?: {
|
|
59
|
+
fileDir?: string | null;
|
|
60
|
+
forceFileFallback?: boolean;
|
|
61
|
+
passphrase?: string | null;
|
|
62
|
+
}): void;
|