@the-open-engine/zeroshot 6.3.0 → 6.5.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/cli/commands/providers.js +11 -5
- package/cli/index.js +83 -17
- package/cli/lib/first-run.js +14 -3
- package/docker/zeroshot-cluster/Dockerfile +11 -1
- package/lib/agent-cli-provider/acp-stdio-runner.d.ts +4 -0
- package/lib/agent-cli-provider/acp-stdio-runner.d.ts.map +1 -0
- package/lib/agent-cli-provider/acp-stdio-runner.js +259 -0
- package/lib/agent-cli-provider/acp-stdio-runner.js.map +1 -0
- package/lib/agent-cli-provider/adapters/acp.d.ts +23 -0
- package/lib/agent-cli-provider/adapters/acp.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/acp.js +373 -0
- package/lib/agent-cli-provider/adapters/acp.js.map +1 -0
- package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/claude.js +2 -29
- package/lib/agent-cli-provider/adapters/claude.js.map +1 -1
- package/lib/agent-cli-provider/adapters/copilot-parser.d.ts +3 -0
- package/lib/agent-cli-provider/adapters/copilot-parser.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/copilot-parser.js +154 -0
- package/lib/agent-cli-provider/adapters/copilot-parser.js.map +1 -0
- package/lib/agent-cli-provider/adapters/copilot.d.ts +3 -0
- package/lib/agent-cli-provider/adapters/copilot.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/copilot.js +176 -0
- package/lib/agent-cli-provider/adapters/copilot.js.map +1 -0
- package/lib/agent-cli-provider/adapters/gateway.d.ts +6 -0
- package/lib/agent-cli-provider/adapters/gateway.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/gateway.js +161 -0
- package/lib/agent-cli-provider/adapters/gateway.js.map +1 -0
- package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/gemini.js +9 -2
- package/lib/agent-cli-provider/adapters/gemini.js.map +1 -1
- package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/index.js +6 -34
- package/lib/agent-cli-provider/adapters/index.js.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/opencode.js +5 -1
- package/lib/agent-cli-provider/adapters/opencode.js.map +1 -1
- package/lib/agent-cli-provider/adapters/pi.d.ts +3 -0
- package/lib/agent-cli-provider/adapters/pi.d.ts.map +1 -0
- package/lib/agent-cli-provider/adapters/pi.js +331 -0
- package/lib/agent-cli-provider/adapters/pi.js.map +1 -0
- package/lib/agent-cli-provider/claude-command.d.ts +6 -0
- package/lib/agent-cli-provider/claude-command.d.ts.map +1 -0
- package/lib/agent-cli-provider/claude-command.js +43 -0
- package/lib/agent-cli-provider/claude-command.js.map +1 -0
- package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-actions.js +13 -17
- package/lib/agent-cli-provider/contract-actions.js.map +1 -1
- package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-invoke.js +10 -3
- package/lib/agent-cli-provider/contract-invoke.js.map +1 -1
- package/lib/agent-cli-provider/contract-options.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-options.js +57 -2
- package/lib/agent-cli-provider/contract-options.js.map +1 -1
- package/lib/agent-cli-provider/contract-support.d.ts +1 -0
- package/lib/agent-cli-provider/contract-support.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-support.js +25 -3
- package/lib/agent-cli-provider/contract-support.js.map +1 -1
- package/lib/agent-cli-provider/errors.d.ts +1 -0
- package/lib/agent-cli-provider/errors.d.ts.map +1 -1
- package/lib/agent-cli-provider/errors.js +14 -5
- package/lib/agent-cli-provider/errors.js.map +1 -1
- package/lib/agent-cli-provider/gateway-client.d.ts +32 -0
- package/lib/agent-cli-provider/gateway-client.d.ts.map +1 -0
- package/lib/agent-cli-provider/gateway-client.js +135 -0
- package/lib/agent-cli-provider/gateway-client.js.map +1 -0
- package/lib/agent-cli-provider/gateway-runner.d.ts +9 -0
- package/lib/agent-cli-provider/gateway-runner.d.ts.map +1 -0
- package/lib/agent-cli-provider/gateway-runner.js +294 -0
- package/lib/agent-cli-provider/gateway-runner.js.map +1 -0
- package/lib/agent-cli-provider/gateway-tools.d.ts +14 -0
- package/lib/agent-cli-provider/gateway-tools.d.ts.map +1 -0
- package/lib/agent-cli-provider/gateway-tools.js +495 -0
- package/lib/agent-cli-provider/gateway-tools.js.map +1 -0
- package/lib/agent-cli-provider/index.d.ts +3 -2
- package/lib/agent-cli-provider/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/index.js +14 -1
- package/lib/agent-cli-provider/index.js.map +1 -1
- package/lib/agent-cli-provider/invoke-evidence.d.ts +2 -2
- package/lib/agent-cli-provider/invoke-evidence.d.ts.map +1 -1
- package/lib/agent-cli-provider/invoke-evidence.js +17 -3
- package/lib/agent-cli-provider/invoke-evidence.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +437 -0
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -0
- package/lib/agent-cli-provider/provider-registry.js +411 -0
- package/lib/agent-cli-provider/provider-registry.js.map +1 -0
- package/lib/agent-cli-provider/single-agent-runtime.d.ts +7 -0
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +139 -19
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/agent-cli-provider/types.d.ts +106 -4
- package/lib/agent-cli-provider/types.d.ts.map +1 -1
- package/lib/agent-cli-provider/types.js.map +1 -1
- package/lib/detached-startup.js +4 -2
- package/lib/docker-config.js +24 -13
- package/lib/provider-defaults.js +15 -4
- package/lib/provider-detection.js +2 -0
- package/lib/provider-names.js +32 -12
- package/lib/repo-settings.js +15 -1
- package/lib/run-mode.js +18 -6
- package/lib/run-plan.js +32 -0
- package/lib/settings/claude-auth.js +3 -6
- package/lib/settings.js +17 -2
- package/lib/setup-apply.js +300 -0
- package/lib/setup-journal.js +109 -0
- package/lib/setup-plan.js +406 -0
- package/lib/setup-undo.js +88 -0
- package/lib/start-cluster.js +34 -9
- package/lib/stream-json-parser.js +7 -5
- package/package.json +33 -3
- package/scripts/live-provider-smoke.js +221 -0
- package/src/agent/agent-lifecycle.js +7 -4
- package/src/agent/agent-quality-gate-schema.js +2 -2
- package/src/agent/agent-task-executor.js +41 -2
- package/src/agent-cli-provider/acp-stdio-runner.ts +314 -0
- package/src/agent-cli-provider/adapters/acp.ts +493 -0
- package/src/agent-cli-provider/adapters/claude.ts +2 -32
- package/src/agent-cli-provider/adapters/copilot-parser.ts +166 -0
- package/src/agent-cli-provider/adapters/copilot.ts +231 -0
- package/src/agent-cli-provider/adapters/gateway.ts +186 -0
- package/src/agent-cli-provider/adapters/gemini.ts +9 -2
- package/src/agent-cli-provider/adapters/index.ts +5 -36
- package/src/agent-cli-provider/adapters/opencode.ts +4 -1
- package/src/agent-cli-provider/adapters/pi.ts +410 -0
- package/src/agent-cli-provider/claude-command.ts +47 -0
- package/src/agent-cli-provider/contract-actions.ts +14 -17
- package/src/agent-cli-provider/contract-invoke.ts +12 -3
- package/src/agent-cli-provider/contract-options.ts +72 -3
- package/src/agent-cli-provider/contract-support.ts +30 -3
- package/src/agent-cli-provider/errors.ts +14 -4
- package/src/agent-cli-provider/gateway-client.ts +170 -0
- package/src/agent-cli-provider/gateway-runner.ts +353 -0
- package/src/agent-cli-provider/gateway-tools.ts +616 -0
- package/src/agent-cli-provider/index.ts +28 -0
- package/src/agent-cli-provider/invoke-evidence.ts +24 -3
- package/src/agent-cli-provider/provider-registry.ts +515 -0
- package/src/agent-cli-provider/single-agent-runtime.ts +192 -18
- package/src/agent-cli-provider/types.ts +145 -4
- package/src/config-validator.js +33 -15
- package/src/isolation-manager.js +124 -19
- package/src/ledger.js +3 -0
- package/src/message-bus.js +12 -2
- package/src/orchestrator.js +37 -17
- package/src/preflight.js +83 -30
- package/src/providers/capabilities.js +15 -42
- package/src/providers/index.js +52 -72
- package/src/worktree-claude-config.js +17 -0
- package/task-lib/commands/run.js +1 -0
- package/task-lib/provider-helper-runtime.js +11 -0
- package/task-lib/runner.js +7 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup plan — read-only facts collector + the pinned, versioned setup contract.
|
|
3
|
+
*
|
|
4
|
+
* buildSetupPlan() is pure over its injected inputs: no direct process.env/fs
|
|
5
|
+
* reads for config data, no writes, no prompts. Everything downstream (apply,
|
|
6
|
+
* undo, the TTY wizard, agents) consumes the object this returns, so its shape
|
|
7
|
+
* (schemaVersion, facts, decisions, recommended, risk, proposedWrites) and the
|
|
8
|
+
* decisionId registry below are a stable contract — do not rename IDs or add a
|
|
9
|
+
* parallel run-mode field without updating every consumer.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const SCHEMA_VERSION = 1;
|
|
15
|
+
|
|
16
|
+
// Canonical settings key each decision maps to. `defaultIsolation` and
|
|
17
|
+
// `defaultDelivery` MUST stay pinned to the keys resolveEffectiveRunPlan
|
|
18
|
+
// already reads (today: settings.defaultDocker) — see the canonical-path
|
|
19
|
+
// rule in issue #605. Never introduce a second parallel key here.
|
|
20
|
+
const DECISION_PATHS = {
|
|
21
|
+
defaultProvider: { scope: 'global', path: 'defaultProvider' },
|
|
22
|
+
defaultIsolation: { scope: 'global', path: 'defaultDocker' },
|
|
23
|
+
allowLocalNoIsolation: { scope: 'global', path: 'allowLocalNoIsolation' },
|
|
24
|
+
defaultDelivery: { scope: 'global', path: 'defaultDelivery' },
|
|
25
|
+
defaultIssueSource: { scope: 'global', path: 'defaultIssueSource' },
|
|
26
|
+
prBase: { scope: 'repo', path: 'prBase' },
|
|
27
|
+
dockerMounts: { scope: 'global', path: 'dockerMounts' },
|
|
28
|
+
dockerEnvPassthrough: { scope: 'global', path: 'dockerEnvPassthrough' },
|
|
29
|
+
updatePolicy: { scope: 'global', path: 'updatePolicy' },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function providerLevelDecisionId(providerName) {
|
|
33
|
+
return `providerLevel.${providerName}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Settings keys a run-mode resolver actually reads today. Shared by
|
|
37
|
+
// buildProposedWrites below (never propose a write nobody will read) and by
|
|
38
|
+
// lib/setup-apply.js (never perform a write nobody will read) — one
|
|
39
|
+
// canonical answer to "is this key consumed?" so the two can't drift.
|
|
40
|
+
const CONSUMED_PATHS = new Set([
|
|
41
|
+
'global:defaultProvider',
|
|
42
|
+
'global:defaultDocker',
|
|
43
|
+
'global:defaultDelivery',
|
|
44
|
+
'global:defaultIssueSource',
|
|
45
|
+
'global:dockerMounts',
|
|
46
|
+
'global:dockerEnvPassthrough',
|
|
47
|
+
// No resolver consumes this yet; consumption is deferred to a future
|
|
48
|
+
// update-policy issue, but issue #606 explicitly sanctions writing it now.
|
|
49
|
+
'global:updatePolicy',
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
function isConsumedPath(scope, targetPath) {
|
|
53
|
+
if (scope === 'global' && targetPath.startsWith('providerSettings.')) return true;
|
|
54
|
+
return CONSUMED_PATHS.has(`${scope}:${targetPath}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// providerLevel.<provider> decisionIds map to a per-provider settings key
|
|
58
|
+
// (providerSettings.<provider>) not present in DECISION_PATHS above, since
|
|
59
|
+
// the provider name is only known at runtime.
|
|
60
|
+
function resolveDecisionPath(decisionId) {
|
|
61
|
+
if (decisionId.startsWith('providerLevel.')) {
|
|
62
|
+
const providerName = decisionId.slice('providerLevel.'.length);
|
|
63
|
+
return { scope: 'global', path: `providerSettings.${providerName}` };
|
|
64
|
+
}
|
|
65
|
+
return DECISION_PATHS[decisionId] || null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getNestedValue(source, pathStr) {
|
|
69
|
+
return pathStr
|
|
70
|
+
.split('.')
|
|
71
|
+
.reduce((acc, key) => (acc === null || acc === undefined ? undefined : acc[key]), source);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function defaultDeps() {
|
|
75
|
+
const { commandExists, getCommandPath } = require('./provider-detection');
|
|
76
|
+
const { checkDocker, checkGhAuth } = require('../src/preflight');
|
|
77
|
+
const { execSync } = require('../src/lib/safe-exec');
|
|
78
|
+
const { listProviders, getProvider } = require('../src/providers');
|
|
79
|
+
const { getProviderDefaults } = require('./provider-defaults');
|
|
80
|
+
const packageJson = require('../package.json');
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
commandExists,
|
|
84
|
+
getCommandPath,
|
|
85
|
+
checkDocker,
|
|
86
|
+
checkGhAuth,
|
|
87
|
+
execSync,
|
|
88
|
+
listProviders,
|
|
89
|
+
getProvider,
|
|
90
|
+
getProviderDefaults,
|
|
91
|
+
getNodeVersion: () => process.version,
|
|
92
|
+
getPackageVersion: () => packageJson.version,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function detectInstallSource(cwd, env) {
|
|
97
|
+
if (env.npm_config_global === 'true') return 'npm-global';
|
|
98
|
+
if (env.npm_execpath && /_npx|npx/.test(env.npm_execpath)) return 'npx';
|
|
99
|
+
try {
|
|
100
|
+
const ownNodeModules = path.join(__dirname, '..', 'node_modules');
|
|
101
|
+
if (cwd && (cwd === path.join(__dirname, '..') || cwd.startsWith(ownNodeModules))) {
|
|
102
|
+
return 'local';
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// fall through to unknown
|
|
106
|
+
}
|
|
107
|
+
return 'unknown';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function buildNodeFacts({ cwd, env, deps }) {
|
|
111
|
+
return {
|
|
112
|
+
version: deps.getNodeVersion(),
|
|
113
|
+
packageVersion: deps.getPackageVersion(),
|
|
114
|
+
installSource: detectInstallSource(cwd, env),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function buildProviderFacts(deps) {
|
|
119
|
+
const providers = {};
|
|
120
|
+
for (const name of deps.listProviders()) {
|
|
121
|
+
let cliCommand = name;
|
|
122
|
+
try {
|
|
123
|
+
cliCommand = deps.getProvider(name).cliCommand || name;
|
|
124
|
+
} catch {
|
|
125
|
+
// Provider metadata unavailable — fall back to the provider name as the CLI command.
|
|
126
|
+
}
|
|
127
|
+
const cliAvailable = deps.commandExists(cliCommand);
|
|
128
|
+
providers[name] = {
|
|
129
|
+
cliAvailable,
|
|
130
|
+
path: cliAvailable ? deps.getCommandPath(cliCommand) : null,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return providers;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function safeExecTrim(deps, command, cwd) {
|
|
137
|
+
try {
|
|
138
|
+
return deps.execSync(command, { cwd, stdio: 'pipe', encoding: 'utf8' }).trim();
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function buildGitFacts({ cwd, deps }) {
|
|
145
|
+
const isRepo = safeExecTrim(deps, 'git rev-parse --is-inside-work-tree', cwd) === 'true';
|
|
146
|
+
const ghAvailable = deps.commandExists('gh');
|
|
147
|
+
|
|
148
|
+
if (!isRepo) {
|
|
149
|
+
return { isRepo: false, branch: null, remote: null, ghAvailable, ghAuthed: null };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const branch = safeExecTrim(deps, 'git rev-parse --abbrev-ref HEAD', cwd);
|
|
153
|
+
const remote = safeExecTrim(deps, 'git remote get-url origin', cwd);
|
|
154
|
+
const ghAuthed = ghAvailable ? !!deps.checkGhAuth().authenticated : null;
|
|
155
|
+
|
|
156
|
+
return { isRepo: true, branch, remote, ghAvailable, ghAuthed };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function buildFacts({ cwd, settings, repoSettings, env, deps }) {
|
|
160
|
+
return {
|
|
161
|
+
node: buildNodeFacts({ cwd, env, deps }),
|
|
162
|
+
providers: buildProviderFacts(deps),
|
|
163
|
+
git: buildGitFacts({ cwd, deps }),
|
|
164
|
+
docker: { available: !!deps.checkDocker().available },
|
|
165
|
+
settings: {
|
|
166
|
+
hasGlobal: settings?.__meta ? !!settings.__meta.fileExists : true,
|
|
167
|
+
hasRepo: repoSettings !== null && repoSettings !== undefined,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function inferIssueSource(facts) {
|
|
173
|
+
const { parseGitRemoteUrl } = require('./git-remote-utils');
|
|
174
|
+
const parsed = parseGitRemoteUrl(facts.git.remote);
|
|
175
|
+
return parsed?.provider || null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function inferPrBase(cwd, deps) {
|
|
179
|
+
const branch = safeExecTrim(deps, 'git rev-parse --abbrev-ref origin/HEAD', cwd);
|
|
180
|
+
if (!branch) return null;
|
|
181
|
+
return branch.replace(/^origin\//, '');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function buildProviderLevelRecommendation(name, deps) {
|
|
185
|
+
const providerDefaults = deps.getProviderDefaults()[name] || {};
|
|
186
|
+
const minLevel = providerDefaults.minLevel;
|
|
187
|
+
const defaultLevel = providerDefaults.defaultLevel;
|
|
188
|
+
const maxLevel = providerDefaults.maxLevel;
|
|
189
|
+
const overrides = providerDefaults.levelOverrides || {};
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const provider = deps.getProvider(name);
|
|
193
|
+
return {
|
|
194
|
+
min: provider.resolveModelSpec(minLevel, overrides).model,
|
|
195
|
+
default: provider.resolveModelSpec(defaultLevel, overrides).model,
|
|
196
|
+
max: provider.resolveModelSpec(maxLevel, overrides).model,
|
|
197
|
+
};
|
|
198
|
+
} catch {
|
|
199
|
+
return { min: null, default: null, max: null };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function buildRecommendedAndRisk({ cwd, facts, env, deps }) {
|
|
204
|
+
const recommended = {};
|
|
205
|
+
const risk = {};
|
|
206
|
+
|
|
207
|
+
const firstAvailableProvider = Object.entries(facts.providers).find(
|
|
208
|
+
([, info]) => info.cliAvailable
|
|
209
|
+
);
|
|
210
|
+
recommended.defaultProvider = firstAvailableProvider ? firstAvailableProvider[0] : 'claude';
|
|
211
|
+
risk.defaultProvider = firstAvailableProvider ? 'low' : 'medium';
|
|
212
|
+
|
|
213
|
+
for (const name of Object.keys(facts.providers)) {
|
|
214
|
+
recommended[providerLevelDecisionId(name)] = buildProviderLevelRecommendation(name, deps);
|
|
215
|
+
risk[providerLevelDecisionId(name)] = 'low';
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (facts.git.isRepo) {
|
|
219
|
+
recommended.defaultIsolation = 'worktree';
|
|
220
|
+
risk.defaultIsolation = 'low';
|
|
221
|
+
} else if (facts.docker.available) {
|
|
222
|
+
recommended.defaultIsolation = 'docker';
|
|
223
|
+
risk.defaultIsolation = 'low';
|
|
224
|
+
} else {
|
|
225
|
+
recommended.defaultIsolation = 'none';
|
|
226
|
+
risk.defaultIsolation = 'high';
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
recommended.allowLocalNoIsolation = false;
|
|
230
|
+
risk.allowLocalNoIsolation = 'low';
|
|
231
|
+
|
|
232
|
+
recommended.defaultDelivery = 'none';
|
|
233
|
+
risk.defaultDelivery = 'low';
|
|
234
|
+
|
|
235
|
+
const inferredIssueSource = inferIssueSource(facts);
|
|
236
|
+
recommended.defaultIssueSource = inferredIssueSource || 'github';
|
|
237
|
+
risk.defaultIssueSource = inferredIssueSource ? 'low' : 'medium';
|
|
238
|
+
|
|
239
|
+
const inferredPrBase = inferPrBase(cwd, deps);
|
|
240
|
+
recommended.prBase = inferredPrBase || 'main';
|
|
241
|
+
risk.prBase = inferredPrBase ? 'low' : 'medium';
|
|
242
|
+
|
|
243
|
+
recommended.dockerMounts = ['gh', 'git', 'ssh'];
|
|
244
|
+
risk.dockerMounts = 'low';
|
|
245
|
+
|
|
246
|
+
recommended.dockerEnvPassthrough = [];
|
|
247
|
+
risk.dockerEnvPassthrough = 'low';
|
|
248
|
+
|
|
249
|
+
const nonInteractive = env.CI === 'true' || env.__isTTY === false;
|
|
250
|
+
recommended.updatePolicy = nonInteractive ? 'off' : 'notify';
|
|
251
|
+
risk.updatePolicy = 'low';
|
|
252
|
+
|
|
253
|
+
return { recommended, risk, inferredIssueSource, inferredPrBase };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function currentValueFor(decisionId, settings, repoSettings) {
|
|
257
|
+
const target = resolveDecisionPath(decisionId);
|
|
258
|
+
if (!target) return null;
|
|
259
|
+
const source = target.scope === 'repo' ? repoSettings || {} : settings || {};
|
|
260
|
+
const value = getNestedValue(source, target.path);
|
|
261
|
+
return value === undefined ? null : value;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function buildDecisions({ facts, settings, repoSettings, inferredIssueSource, inferredPrBase }) {
|
|
265
|
+
const decisions = [];
|
|
266
|
+
const hasGlobal = facts.settings.hasGlobal;
|
|
267
|
+
const hasRepo = facts.settings.hasRepo;
|
|
268
|
+
|
|
269
|
+
const globalDecisionIds = [
|
|
270
|
+
'defaultProvider',
|
|
271
|
+
...Object.keys(facts.providers).map(providerLevelDecisionId),
|
|
272
|
+
'defaultIsolation',
|
|
273
|
+
'allowLocalNoIsolation',
|
|
274
|
+
'defaultDelivery',
|
|
275
|
+
'defaultIssueSource',
|
|
276
|
+
'dockerMounts',
|
|
277
|
+
'dockerEnvPassthrough',
|
|
278
|
+
'updatePolicy',
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
for (const decisionId of globalDecisionIds) {
|
|
282
|
+
const shouldInclude =
|
|
283
|
+
!hasGlobal || (decisionId === 'defaultIssueSource' && !inferredIssueSource);
|
|
284
|
+
if (!shouldInclude) continue;
|
|
285
|
+
decisions.push({
|
|
286
|
+
decisionId,
|
|
287
|
+
domain: domainFor(decisionId),
|
|
288
|
+
currentValue: currentValueFor(decisionId, settings, repoSettings),
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (!hasRepo || !inferredPrBase) {
|
|
293
|
+
decisions.push({
|
|
294
|
+
decisionId: 'prBase',
|
|
295
|
+
domain: domainFor('prBase'),
|
|
296
|
+
currentValue: currentValueFor('prBase', settings, repoSettings),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return decisions;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function domainFor(decisionId) {
|
|
304
|
+
if (decisionId.startsWith('providerLevel.')) return '{ min, default, max } of haiku|sonnet|opus';
|
|
305
|
+
const domains = {
|
|
306
|
+
defaultProvider: 'claude | codex | gemini | opencode',
|
|
307
|
+
defaultIsolation: 'worktree | docker | none',
|
|
308
|
+
allowLocalNoIsolation: 'boolean',
|
|
309
|
+
defaultDelivery: 'none | pr | ship',
|
|
310
|
+
defaultIssueSource: 'github | gitlab | jira | azure-devops | linear',
|
|
311
|
+
prBase: 'string (branch)',
|
|
312
|
+
dockerMounts: 'array of presets/objects',
|
|
313
|
+
dockerEnvPassthrough: 'string[]',
|
|
314
|
+
updatePolicy: 'off | notify | auto',
|
|
315
|
+
};
|
|
316
|
+
return domains[decisionId] || 'unknown';
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function buildProposedWrites({ decisions, recommended }) {
|
|
320
|
+
const writes = [];
|
|
321
|
+
for (const decision of decisions) {
|
|
322
|
+
const target = resolveDecisionPath(decision.decisionId);
|
|
323
|
+
if (!target) continue;
|
|
324
|
+
// A decision can still be surfaced for the user to make (e.g. a future
|
|
325
|
+
// wizard asking about prBase), but proposing a *write* for a settings key
|
|
326
|
+
// no resolver reads would advertise a write that apply will always skip —
|
|
327
|
+
// dead config. Only propose writes apply will actually perform.
|
|
328
|
+
if (!isConsumedPath(target.scope, target.path)) continue;
|
|
329
|
+
let to = recommended[decision.decisionId];
|
|
330
|
+
if (decision.decisionId === 'defaultIsolation') {
|
|
331
|
+
to = to === 'docker';
|
|
332
|
+
}
|
|
333
|
+
if (to === decision.currentValue) continue;
|
|
334
|
+
writes.push({
|
|
335
|
+
scope: target.scope,
|
|
336
|
+
path: target.path,
|
|
337
|
+
from: decision.currentValue ?? null,
|
|
338
|
+
to,
|
|
339
|
+
decisionId: decision.decisionId,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
return writes;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Build the pinned, versioned setup contract. Pure over injected inputs —
|
|
347
|
+
* performs only cheap, read-only detection (no writes, no prompts).
|
|
348
|
+
*
|
|
349
|
+
* @param {Object} params
|
|
350
|
+
* @param {string} params.cwd
|
|
351
|
+
* @param {Object} params.settings - loaded global settings (optionally with __meta.fileExists)
|
|
352
|
+
* @param {Object|null} params.repoSettings - repo-local settings object, or null
|
|
353
|
+
* @param {Object} params.env - caller-provided env (e.g. process.env), plus optional __isTTY
|
|
354
|
+
* @param {Object} [params.deps] - injected dependencies (for testing)
|
|
355
|
+
* @returns {Object} plan
|
|
356
|
+
*/
|
|
357
|
+
function buildSetupPlan({ cwd, settings, repoSettings, env, deps } = {}) {
|
|
358
|
+
const resolvedDeps = { ...defaultDeps(), ...(deps || {}) };
|
|
359
|
+
const resolvedEnv = env || {};
|
|
360
|
+
const resolvedCwd = cwd || '.';
|
|
361
|
+
const resolvedSettings = settings || {};
|
|
362
|
+
|
|
363
|
+
const facts = buildFacts({
|
|
364
|
+
cwd: resolvedCwd,
|
|
365
|
+
settings: resolvedSettings,
|
|
366
|
+
repoSettings,
|
|
367
|
+
env: resolvedEnv,
|
|
368
|
+
deps: resolvedDeps,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const { recommended, risk, inferredIssueSource, inferredPrBase } = buildRecommendedAndRisk({
|
|
372
|
+
cwd: resolvedCwd,
|
|
373
|
+
facts,
|
|
374
|
+
env: resolvedEnv,
|
|
375
|
+
deps: resolvedDeps,
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
const decisions = buildDecisions({
|
|
379
|
+
facts,
|
|
380
|
+
settings: resolvedSettings,
|
|
381
|
+
repoSettings,
|
|
382
|
+
inferredIssueSource,
|
|
383
|
+
inferredPrBase,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
const proposedWrites = buildProposedWrites({ decisions, recommended });
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
schemaVersion: SCHEMA_VERSION,
|
|
390
|
+
facts,
|
|
391
|
+
decisions,
|
|
392
|
+
recommended,
|
|
393
|
+
risk,
|
|
394
|
+
proposedWrites,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
module.exports = {
|
|
399
|
+
buildSetupPlan,
|
|
400
|
+
resolveDecisionPath,
|
|
401
|
+
domainFor,
|
|
402
|
+
DECISION_PATHS,
|
|
403
|
+
getNestedValue,
|
|
404
|
+
isConsumedPath,
|
|
405
|
+
CONSUMED_PATHS,
|
|
406
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `zeroshot setup undo` — reverts writes made by `zeroshot setup apply` using
|
|
3
|
+
* the journal recorded at apply time (lib/setup-journal.js).
|
|
4
|
+
*
|
|
5
|
+
* Three-way conflict rule per journaled write, comparing `current` against
|
|
6
|
+
* `appliedValue`:
|
|
7
|
+
* - current === appliedValue -> restore priorValue (delete if null)
|
|
8
|
+
* - current === priorValue -> already-restored (no-op)
|
|
9
|
+
* - otherwise (changed elsewhere) -> skipped-modified, never clobbered
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
loadJournal,
|
|
14
|
+
getNestedValue,
|
|
15
|
+
setNestedValue,
|
|
16
|
+
deleteNestedKey,
|
|
17
|
+
deepEqual,
|
|
18
|
+
} = require('./setup-journal');
|
|
19
|
+
|
|
20
|
+
function defaultUndoDeps() {
|
|
21
|
+
const { loadSettings, saveSettings } = require('./settings');
|
|
22
|
+
const { readRepoSettings, writeRepoSettings } = require('./repo-settings');
|
|
23
|
+
|
|
24
|
+
return { loadSettings, saveSettings, readRepoSettings, writeRepoSettings };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Undo every journaled write, per the three-way conflict rule.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} [params]
|
|
31
|
+
* @param {Object} [params.deps] - Injected dependencies (for testing).
|
|
32
|
+
* @returns {Array<{scope: string, path: string, repoRoot: string|null, status: string, current?: *, wouldRestore?: *}>}
|
|
33
|
+
*/
|
|
34
|
+
function undo({ deps = {} } = {}) {
|
|
35
|
+
const resolvedDeps = { ...defaultUndoDeps(), ...deps };
|
|
36
|
+
const journal = loadJournal();
|
|
37
|
+
|
|
38
|
+
const globalSettings = resolvedDeps.loadSettings();
|
|
39
|
+
const repoSettingsCache = new Map();
|
|
40
|
+
let globalDirty = false;
|
|
41
|
+
const dirtyRepoRoots = new Set();
|
|
42
|
+
|
|
43
|
+
function repoSettingsFor(repoRoot) {
|
|
44
|
+
if (!repoSettingsCache.has(repoRoot)) {
|
|
45
|
+
const { settings } = resolvedDeps.readRepoSettings(repoRoot);
|
|
46
|
+
repoSettingsCache.set(repoRoot, settings || {});
|
|
47
|
+
}
|
|
48
|
+
return repoSettingsCache.get(repoRoot);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const results = journal.entries.map((entry) => {
|
|
52
|
+
const settingsObj = entry.scope === 'repo' ? repoSettingsFor(entry.repoRoot) : globalSettings;
|
|
53
|
+
const current = getNestedValue(settingsObj, entry.path) ?? null;
|
|
54
|
+
|
|
55
|
+
if (deepEqual(current, entry.priorValue)) {
|
|
56
|
+
return { ...entry, status: 'already-restored' };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!deepEqual(current, entry.appliedValue)) {
|
|
60
|
+
return { ...entry, status: 'skipped-modified', current, wouldRestore: entry.priorValue };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (entry.priorValue === null) {
|
|
64
|
+
deleteNestedKey(settingsObj, entry.path);
|
|
65
|
+
} else {
|
|
66
|
+
setNestedValue(settingsObj, entry.path, entry.priorValue);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (entry.scope === 'repo') {
|
|
70
|
+
dirtyRepoRoots.add(entry.repoRoot);
|
|
71
|
+
} else {
|
|
72
|
+
globalDirty = true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { ...entry, status: entry.priorValue === null ? 'deleted' : 'restored' };
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if (globalDirty) resolvedDeps.saveSettings(globalSettings);
|
|
79
|
+
for (const repoRoot of dirtyRepoRoots) {
|
|
80
|
+
resolvedDeps.writeRepoSettings(repoRoot, repoSettingsFor(repoRoot));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Journal entries are left in place (not cleared) so a re-run reports
|
|
84
|
+
// 'already-restored' instead of finding nothing to undo.
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { undo };
|
package/lib/start-cluster.js
CHANGED
|
@@ -5,7 +5,8 @@ const { normalizeProviderName } = require('./provider-names');
|
|
|
5
5
|
const { getProvider } = require('../src/providers');
|
|
6
6
|
const { detectProvider } = require('../src/issue-providers');
|
|
7
7
|
const TemplateResolver = require('../src/template-resolver');
|
|
8
|
-
const {
|
|
8
|
+
const { runModeFromPlan } = require('./run-mode');
|
|
9
|
+
const { resolveRunPlan } = require('./run-plan');
|
|
9
10
|
|
|
10
11
|
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
11
12
|
|
|
@@ -198,8 +199,20 @@ function mergeRunOptions(options) {
|
|
|
198
199
|
return envRunOptions ? { ...envRunOptions, ...options } : options;
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
// The single producer of the run plan for a cluster start: fold env + settings
|
|
203
|
+
// into the flags, then resolve the canonical isolation/delivery/autoMerge plan.
|
|
204
|
+
// buildStartOptions reads EVERY mode field off this one plan — no field
|
|
205
|
+
// (isolation, worktree, autoPr, autoMerge, runMode) is derived independently.
|
|
206
|
+
function resolveEffectiveRunPlan(mergedOptions, settings) {
|
|
207
|
+
return resolveRunPlan({
|
|
208
|
+
...mergedOptions,
|
|
209
|
+
docker: anyTruthy(
|
|
210
|
+
mergedOptions.docker,
|
|
211
|
+
process.env.ZEROSHOT_DOCKER === '1',
|
|
212
|
+
settings.defaultDocker
|
|
213
|
+
),
|
|
214
|
+
worktree: anyTruthy(mergedOptions.worktree, process.env.ZEROSHOT_WORKTREE === '1'),
|
|
215
|
+
});
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
function resolveMergeQueue(mergedOptions) {
|
|
@@ -238,14 +251,15 @@ function buildStartOptions({
|
|
|
238
251
|
forceProvider,
|
|
239
252
|
}) {
|
|
240
253
|
const mergedOptions = mergeRunOptions(options);
|
|
254
|
+
const plan = resolveEffectiveRunPlan(mergedOptions, settings);
|
|
241
255
|
return {
|
|
242
256
|
clusterId,
|
|
243
257
|
cwd: resolveTargetCwd(),
|
|
244
|
-
isolation:
|
|
258
|
+
isolation: plan.isolation === 'docker',
|
|
245
259
|
isolationImage: firstTruthy(mergedOptions.dockerImage, process.env.ZEROSHOT_DOCKER_IMAGE),
|
|
246
|
-
worktree:
|
|
247
|
-
autoPr:
|
|
248
|
-
autoMerge:
|
|
260
|
+
worktree: plan.isolation === 'worktree',
|
|
261
|
+
autoPr: plan.delivery !== 'none',
|
|
262
|
+
autoMerge: plan.autoMerge,
|
|
249
263
|
autoPush: process.env.ZEROSHOT_PUSH === '1',
|
|
250
264
|
modelOverride: optionalValue(modelOverride),
|
|
251
265
|
providerOverride: optionalValue(providerOverride),
|
|
@@ -257,7 +271,7 @@ function buildStartOptions({
|
|
|
257
271
|
mergeQueue: resolveMergeQueue(mergedOptions),
|
|
258
272
|
closeIssue: resolveCloseIssue(mergedOptions),
|
|
259
273
|
ship: mergedOptions.ship,
|
|
260
|
-
runMode:
|
|
274
|
+
runMode: runModeFromPlan(plan),
|
|
261
275
|
requiredQualityGates: mergedOptions.requiredQualityGates,
|
|
262
276
|
settings,
|
|
263
277
|
};
|
|
@@ -281,6 +295,16 @@ function resolveConfigOrThrow({
|
|
|
281
295
|
return loadClusterConfig(orchestrator, resolvedPath, settings, providerOverride);
|
|
282
296
|
}
|
|
283
297
|
|
|
298
|
+
function applyDefaultDeliveryOptions(options, settings) {
|
|
299
|
+
if (settings.defaultDelivery === 'pr') {
|
|
300
|
+
return { ...options, pr: true };
|
|
301
|
+
}
|
|
302
|
+
if (settings.defaultDelivery === 'ship') {
|
|
303
|
+
return { ...options, ship: true };
|
|
304
|
+
}
|
|
305
|
+
return options;
|
|
306
|
+
}
|
|
307
|
+
|
|
284
308
|
function startClusterWithInput(args, input) {
|
|
285
309
|
const { orchestrator, config, configPath, configName, settings, providerOverride } = args;
|
|
286
310
|
if (!orchestrator) {
|
|
@@ -296,7 +320,7 @@ function startClusterWithInput(args, input) {
|
|
|
296
320
|
});
|
|
297
321
|
const startOptions = buildStartOptions({
|
|
298
322
|
clusterId: args.clusterId,
|
|
299
|
-
options: args.options || {},
|
|
323
|
+
options: applyDefaultDeliveryOptions(args.options || {}, settings),
|
|
300
324
|
settings,
|
|
301
325
|
providerOverride,
|
|
302
326
|
modelOverride: args.modelOverride,
|
|
@@ -330,6 +354,7 @@ module.exports = {
|
|
|
330
354
|
resolveConfigPath,
|
|
331
355
|
loadClusterConfig,
|
|
332
356
|
buildStartOptions,
|
|
357
|
+
resolveEffectiveRunPlan,
|
|
333
358
|
startClusterFromText,
|
|
334
359
|
startClusterFromIssue,
|
|
335
360
|
startClusterFromFile,
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Provider parsing is delegated to the helper-backed runtime provider facade.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { getProvider } = require('../src/providers');
|
|
7
|
+
const { getProvider, listProviders } = require('../src/providers');
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
function createProviderParsers() {
|
|
10
|
+
return listProviders().map((name) => getProvider(name));
|
|
11
|
+
}
|
|
11
12
|
|
|
12
13
|
function stripTimestampPrefix(line) {
|
|
13
14
|
if (!line || typeof line !== 'string') return '';
|
|
@@ -28,7 +29,7 @@ function stripTimestampPrefix(line) {
|
|
|
28
29
|
return trimmed;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
function parseEvent(line) {
|
|
32
|
+
function parseEvent(line, providerParsers = createProviderParsers()) {
|
|
32
33
|
const content = stripTimestampPrefix(line);
|
|
33
34
|
if (!content) return null;
|
|
34
35
|
|
|
@@ -52,10 +53,11 @@ function collectEvent(events, event) {
|
|
|
52
53
|
function parseChunk(chunk) {
|
|
53
54
|
const events = [];
|
|
54
55
|
const lines = String(chunk || '').split('\n');
|
|
56
|
+
const providerParsers = createProviderParsers();
|
|
55
57
|
|
|
56
58
|
for (const line of lines) {
|
|
57
59
|
if (!line.trim()) continue;
|
|
58
|
-
collectEvent(events, parseEvent(line));
|
|
60
|
+
collectEvent(events, parseEvent(line, providerParsers));
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
return events;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-open-engine/zeroshot",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
4
4
|
"description": "Multi-agent orchestration engine for Claude, Codex, and Gemini",
|
|
5
5
|
"main": "src/orchestrator.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,12 +11,40 @@
|
|
|
11
11
|
"example": "examples",
|
|
12
12
|
"test": "tests"
|
|
13
13
|
},
|
|
14
|
+
"release": {
|
|
15
|
+
"branches": [
|
|
16
|
+
"main"
|
|
17
|
+
],
|
|
18
|
+
"plugins": [
|
|
19
|
+
[
|
|
20
|
+
"@semantic-release/commit-analyzer",
|
|
21
|
+
{
|
|
22
|
+
"releaseRules": [
|
|
23
|
+
{
|
|
24
|
+
"type": "release",
|
|
25
|
+
"release": "minor"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"@semantic-release/release-notes-generator",
|
|
31
|
+
[
|
|
32
|
+
"@semantic-release/npm",
|
|
33
|
+
{
|
|
34
|
+
"npmPublish": true
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"@semantic-release/github"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
14
40
|
"scripts": {
|
|
15
41
|
"pretest": "npm run build:agent-cli-provider",
|
|
16
42
|
"test": "node tests/run-tests.js",
|
|
17
43
|
"test:unit": "node tests/run-tests.js",
|
|
18
|
-
"test:
|
|
19
|
-
"test:
|
|
44
|
+
"test:e2e": "mocha 'tests/e2e/**/*.test.js' --timeout 120000",
|
|
45
|
+
"test:e2e:docker": "bash tests/integration/e2e-isolation-and-auto.test.sh",
|
|
46
|
+
"test:slow": "mocha 'tests/integration/**/*.test.js' 'tests/providers/**/*.test.js' --timeout 180000",
|
|
47
|
+
"test:all": "npm run test && npm run test:e2e && npm run test:slow",
|
|
20
48
|
"test:coverage": "c8 npm run test:unit",
|
|
21
49
|
"test:coverage:report": "c8 --reporter=html npm run test:unit && echo 'Coverage report generated at coverage/index.html'",
|
|
22
50
|
"postinstall": "node scripts/fix-node-pty-permissions.js && node scripts/check-path.js",
|
|
@@ -26,6 +54,8 @@
|
|
|
26
54
|
"lint:agent-cli-provider": "eslint \"src/agent-cli-provider/**/*.ts\" \"tests/agent-cli-provider/**/*.ts\"",
|
|
27
55
|
"build:agent-cli-provider": "tsc --project tsconfig.agent-cli-provider.build.json",
|
|
28
56
|
"test:agent-cli-provider": "node --test tests/agent-cli-provider/*.test.js",
|
|
57
|
+
"test:providers:live": "npm run build:agent-cli-provider && node scripts/live-provider-smoke.js",
|
|
58
|
+
"check:agent-cli-provider": "npm run check:agent-cli-provider:ci",
|
|
29
59
|
"check:agent-cli-provider:ci": "npm run typecheck:agent-cli-provider && npm run lint:agent-cli-provider && npm run build:agent-cli-provider && npm run test:agent-cli-provider",
|
|
30
60
|
"dev:link": "npm link",
|
|
31
61
|
"lint": "eslint .",
|