salmon-loop 0.2.3 → 0.2.13
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/dist/cli/chat.js +1 -0
- package/dist/cli/commands/chat.js +17 -18
- package/dist/cli/commands/context.js +15 -3
- package/dist/cli/commands/help-format.js +12 -0
- package/dist/cli/commands/registry.js +4 -7
- package/dist/cli/commands/run/config-resolution.js +30 -24
- package/dist/cli/commands/run/handler.js +16 -17
- package/dist/cli/commands/run/loop-params.js +1 -0
- package/dist/cli/commands/run/parse-options.js +2 -2
- package/dist/cli/commands/run/validate-options.js +0 -5
- package/dist/cli/commands/run/verbose.js +2 -7
- package/dist/cli/commands/serve.js +29 -22
- package/dist/cli/locales/en.js +2 -0
- package/dist/cli/program-bootstrap.js +6 -1
- package/dist/cli/program-commands.js +4 -0
- package/dist/cli/program-options.js +1 -0
- package/dist/cli/slash/runtime.js +3 -3
- package/dist/cli/utils/output-format.js +6 -0
- package/dist/cli/utils/resolve-cli-config.js +98 -0
- package/dist/cli/utils/verbose-level.js +8 -0
- package/dist/core/config/load.js +22 -8
- package/dist/core/config/merge.js +27 -0
- package/dist/core/config/paths.js +24 -5
- package/dist/core/config/resolve.js +7 -5
- package/dist/core/config/validate.js +21 -0
- package/dist/core/facades/cli-command-chat.js +1 -1
- package/dist/core/facades/cli-context.js +1 -0
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +8 -0
- package/dist/core/grizzco/steps/preflight.js +4 -1
- package/dist/core/intent/chat-intent.js +0 -4
- package/dist/core/llm/ai-sdk/request-params.js +1 -1
- package/dist/core/protocols/a2a/sdk/executor.js +6 -5
- package/dist/core/protocols/acp/formal-agent.js +163 -20
- package/dist/core/protocols/acp/permission-provider.js +20 -0
- package/dist/core/protocols/shared/execution-request.js +24 -0
- package/dist/core/session/compression.js +4 -4
- package/dist/core/session/manager.js +3 -2
- package/dist/core/strata/layers/worktree.js +4 -4
- package/dist/core/tools/builtin/fs.js +4 -4
- package/dist/interfaces/cli/task-runner.js +4 -3
- package/dist/locales/en.js +52 -0
- package/package.json +3 -3
package/dist/cli/chat.js
CHANGED
|
@@ -266,6 +266,7 @@ export async function startChatMode(options) {
|
|
|
266
266
|
authorizationMode: 'deferred',
|
|
267
267
|
userInputProvider,
|
|
268
268
|
subAgentController,
|
|
269
|
+
permissionMode: options.permissionMode,
|
|
269
270
|
});
|
|
270
271
|
return { kind: 'flow', mode: intentDecision.intent, result };
|
|
271
272
|
})(), CHAT_QUEUE_CONFIG.TASK_TIMEOUT_MS, () => timeoutAbort.abort()).finally(() => {
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createPluginRegistry, createPromptRegistry, createRuntimeLlm, setPluginRegistry, setPromptRegistry, ExtensionConfigError, getLogger, normalizePermissionMode, PluginLoader, resolveConfig, resolveExtensions, } from '../../core/facades/cli-command-chat.js';
|
|
1
|
+
import { createPluginRegistry, createPromptRegistry, createRuntimeLlm, setPluginRegistry, setPromptRegistry, ExtensionConfigError, getLogger, normalizePermissionMode, PluginLoader, resolveExtensions, } from '../../core/facades/cli-command-chat.js';
|
|
3
2
|
import { text } from '../locales/index.js';
|
|
4
|
-
import { resolveAuditScope } from '../utils/audit-scope.js';
|
|
5
3
|
import { resolveLlmOutputPolicyFromCli } from '../utils/llm-output.js';
|
|
6
4
|
import { createOutcomeReporter } from '../utils/outcome-reporter.js';
|
|
5
|
+
import { resolveCliConfig } from '../utils/resolve-cli-config.js';
|
|
7
6
|
import { resolveVerifyOption } from '../utils/verify-resolver.js';
|
|
8
7
|
export async function handleChatCommand(options, command) {
|
|
9
8
|
const allOptions = command.optsWithGlobals();
|
|
10
|
-
const
|
|
9
|
+
const configResult = await resolveCliConfig({
|
|
10
|
+
repo: allOptions.repo,
|
|
11
|
+
cwd: process.cwd(),
|
|
12
|
+
configPath: allOptions.config,
|
|
13
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
14
|
+
auditScope: allOptions.auditScope,
|
|
15
|
+
verbose: allOptions.verbose,
|
|
16
|
+
logMode: allOptions.logMode,
|
|
17
|
+
});
|
|
18
|
+
if (!configResult.ok) {
|
|
19
|
+
getLogger().error(configResult.message, true);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const { resolvedConfig, auditScope, repoPath: runPath, verboseLevel } = configResult;
|
|
11
23
|
const printInstruction = typeof allOptions.print === 'string'
|
|
12
24
|
? allOptions.print
|
|
13
25
|
: undefined;
|
|
@@ -28,19 +40,6 @@ export async function handleChatCommand(options, command) {
|
|
|
28
40
|
setPluginRegistry(languagePlugins);
|
|
29
41
|
setPromptRegistry(createPromptRegistry());
|
|
30
42
|
await PluginLoader.loadPlugins(languagePlugins, runPath);
|
|
31
|
-
const resolvedConfig = await resolveConfig({
|
|
32
|
-
repoRoot: runPath,
|
|
33
|
-
enableConfigFile: true,
|
|
34
|
-
});
|
|
35
|
-
const auditScopeResolution = resolveAuditScope({
|
|
36
|
-
cliValue: allOptions.auditScope,
|
|
37
|
-
configValue: resolvedConfig.observability.audit.scope,
|
|
38
|
-
});
|
|
39
|
-
if (!auditScopeResolution.ok) {
|
|
40
|
-
getLogger().error(text.cli.invalidAuditScope(auditScopeResolution.invalid), true);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
const auditScope = auditScopeResolution.value;
|
|
44
43
|
const rawPermissionMode = allOptions.mode ?? resolvedConfig.permissionMode ?? 'interactive';
|
|
45
44
|
const permissionMode = normalizePermissionMode(rawPermissionMode);
|
|
46
45
|
if (!permissionMode) {
|
|
@@ -94,7 +93,7 @@ export async function handleChatCommand(options, command) {
|
|
|
94
93
|
: allOptions.checkpointStrategy || 'worktree',
|
|
95
94
|
continue: continueSession,
|
|
96
95
|
resumeSessionId,
|
|
97
|
-
verbose:
|
|
96
|
+
verbose: verboseLevel,
|
|
98
97
|
llmOutput,
|
|
99
98
|
markdownTheme: resolvedConfig.markdownTheme,
|
|
100
99
|
markdownRenderMode: resolvedConfig.markdownRenderMode,
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
import { createContextCacheStore, createDefaultPermissionGate, ContextService,
|
|
1
|
+
import { createContextCacheStore, createDefaultPermissionGate, ContextService, getLogger, setChurnRankingPolicy, } from '../../core/facades/cli-context.js';
|
|
2
2
|
import { text } from '../locales/index.js';
|
|
3
|
+
import { resolveCliConfig } from '../utils/resolve-cli-config.js';
|
|
3
4
|
export async function handleContextCommand(options, command) {
|
|
4
5
|
const allOptions = command.optsWithGlobals();
|
|
5
|
-
const
|
|
6
|
+
const configResult = await resolveCliConfig({
|
|
7
|
+
repo: allOptions.repo,
|
|
8
|
+
cwd: process.cwd(),
|
|
9
|
+
configPath: allOptions.config,
|
|
10
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
11
|
+
auditScope: allOptions.auditScope,
|
|
12
|
+
logMode: allOptions.logMode,
|
|
13
|
+
});
|
|
14
|
+
if (!configResult.ok) {
|
|
15
|
+
getLogger().error(configResult.message, true);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const { resolvedConfig, repoPath } = configResult;
|
|
6
19
|
if (options.file && options.selection) {
|
|
7
20
|
getLogger().error(text.cli.fileSelectionConflict, true);
|
|
8
21
|
process.exit(1);
|
|
@@ -26,7 +39,6 @@ export async function handleContextCommand(options, command) {
|
|
|
26
39
|
}
|
|
27
40
|
budgetChars = parsed;
|
|
28
41
|
}
|
|
29
|
-
const resolvedConfig = await resolveConfig({ repoRoot: repoPath });
|
|
30
42
|
setChurnRankingPolicy({
|
|
31
43
|
primaryBoost: resolvedConfig.raw?.context?.churn?.weight?.primary,
|
|
32
44
|
rerankWeight: resolvedConfig.raw?.context?.churn?.weight?.rerank,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function formatHelpRows(items) {
|
|
2
|
+
const rows = items.map((item) => {
|
|
3
|
+
const aliases = item.aliases?.length ? ` (${item.aliases.join(', ')})` : '';
|
|
4
|
+
return {
|
|
5
|
+
label: `${item.name}${aliases}`,
|
|
6
|
+
description: item.description,
|
|
7
|
+
};
|
|
8
|
+
});
|
|
9
|
+
const maxName = Math.max(...rows.map((row) => row.label.length), 0);
|
|
10
|
+
return rows.map((row) => `${row.label}`.padEnd(maxName + 2) + row.description).join('\n');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=help-format.js.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { text } from '../locales/index.js';
|
|
1
2
|
import { allowlistCommand } from './allowlist.js';
|
|
2
3
|
import { configCommand } from './config.js';
|
|
3
4
|
import { exitCommand } from './exit.js';
|
|
5
|
+
import { formatHelpRows } from './help-format.js';
|
|
4
6
|
import { llmOutputCommand } from './llm-output.js';
|
|
5
7
|
import { logModeCommand } from './log-mode.js';
|
|
6
8
|
import { modeCommand } from './mode.js';
|
|
@@ -29,16 +31,11 @@ const baseCommands = [
|
|
|
29
31
|
order: 80,
|
|
30
32
|
execute: ({ emit }) => {
|
|
31
33
|
const visible = commands.filter((c) => !c.hidden);
|
|
32
|
-
const
|
|
33
|
-
const rows = visible.map((cmd) => {
|
|
34
|
-
const paddedName = `${cmd.name}`.padEnd(maxName + 2);
|
|
35
|
-
return `${paddedName}${cmd.description}`;
|
|
36
|
-
});
|
|
37
|
-
const helpMsg = rows.join('\n');
|
|
34
|
+
const helpMsg = formatHelpRows(visible);
|
|
38
35
|
emit({
|
|
39
36
|
type: 'log',
|
|
40
37
|
level: 'info',
|
|
41
|
-
message:
|
|
38
|
+
message: text.cli.helpAvailableCommands(helpMsg),
|
|
42
39
|
timestamp: new Date(),
|
|
43
40
|
});
|
|
44
41
|
},
|
|
@@ -1,37 +1,43 @@
|
|
|
1
|
-
import { redactConfigForPrint
|
|
1
|
+
import { redactConfigForPrint } from '../../../core/config/index.js';
|
|
2
2
|
import { getLogger } from '../../../core/facades/cli-observability.js';
|
|
3
|
-
import {
|
|
3
|
+
import { resolveCliConfig } from '../../utils/resolve-cli-config.js';
|
|
4
4
|
export async function resolveRunConfig(params) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
getLogger().error(msg);
|
|
17
|
-
if (params.outputFormat === 'json') {
|
|
18
|
-
params.writeJsonFailure({ message: msg, errorCode: err.code, repoPath: params.repoPath });
|
|
19
|
-
}
|
|
20
|
-
return { ok: false, exitCode: 1 };
|
|
21
|
-
}
|
|
22
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
23
|
-
getLogger().error(text.config.loadFailed(msg));
|
|
5
|
+
const resolved = await resolveCliConfig({
|
|
6
|
+
repoPath: params.repoPath,
|
|
7
|
+
configPath: params.cliOptions.config,
|
|
8
|
+
enableConfigFile: params.cliOptions.configFile !== false,
|
|
9
|
+
auditScope: params.cliOptions.auditScope,
|
|
10
|
+
verbose: params.cliOptions.verbose,
|
|
11
|
+
outputFormat: params.cliOptions.outputFormat,
|
|
12
|
+
logMode: params.cliOptions.logMode,
|
|
13
|
+
});
|
|
14
|
+
if (!resolved.ok) {
|
|
15
|
+
getLogger().error(resolved.message);
|
|
24
16
|
if (params.outputFormat === 'json') {
|
|
25
|
-
params.writeJsonFailure({
|
|
17
|
+
params.writeJsonFailure({
|
|
18
|
+
message: resolved.message,
|
|
19
|
+
errorCode: resolved.errorCode,
|
|
20
|
+
repoPath: params.repoPath,
|
|
21
|
+
});
|
|
26
22
|
}
|
|
27
23
|
return { ok: false, exitCode: 1 };
|
|
28
24
|
}
|
|
29
25
|
if (params.cliOptions.printConfig) {
|
|
30
|
-
const raw = resolvedConfig.raw || { version: 1 };
|
|
26
|
+
const raw = resolved.resolvedConfig.raw || { version: 1 };
|
|
31
27
|
const redacted = redactConfigForPrint(raw);
|
|
32
28
|
process.stdout.write(JSON.stringify(redacted, null, 2) + '\n');
|
|
33
29
|
return { ok: true, printedConfig: true };
|
|
34
30
|
}
|
|
35
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
ok: true,
|
|
33
|
+
resolvedConfig: {
|
|
34
|
+
repoPath: resolved.repoPath,
|
|
35
|
+
verboseLevel: resolved.verboseLevel,
|
|
36
|
+
outputFormat: resolved.outputFormat,
|
|
37
|
+
headlessOutput: resolved.headlessOutput,
|
|
38
|
+
resolvedConfig: resolved.resolvedConfig,
|
|
39
|
+
auditScope: resolved.auditScope,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
36
42
|
}
|
|
37
43
|
//# sourceMappingURL=config-resolution.js.map
|
|
@@ -3,8 +3,9 @@ import { buildSessionConversationContext, createPluginRegistry, createPromptRegi
|
|
|
3
3
|
import { createStdoutWriter } from '../../headless/stdout-writer.js';
|
|
4
4
|
import { text } from '../../locales/index.js';
|
|
5
5
|
import { StderrLogReporter } from '../../reporters/stderr-log-reporter.js';
|
|
6
|
-
import { resolveAuditScope } from '../../utils/audit-scope.js';
|
|
7
6
|
import { createOutcomeReporter } from '../../utils/outcome-reporter.js';
|
|
7
|
+
import { resolveOutputFormat } from '../../utils/output-format.js';
|
|
8
|
+
import { resolveCliCommonOptions } from '../../utils/resolve-cli-config.js';
|
|
8
9
|
import { buildRunAssistantMessage } from './assistant-message.js';
|
|
9
10
|
import { resolveRunConfig } from './config-resolution.js';
|
|
10
11
|
import { handleEarlyRunCommandErrors } from './early-errors.js';
|
|
@@ -22,7 +23,7 @@ import { createRuntimeLlmAndWarn } from './runtime-llm.js';
|
|
|
22
23
|
import { resolveRunRuntimeOptions } from './runtime-options.js';
|
|
23
24
|
import { initializeSession } from './session.js';
|
|
24
25
|
import { buildStructuredOutputState } from './structured-output.js';
|
|
25
|
-
import { logRunVerboseSummary
|
|
26
|
+
import { logRunVerboseSummary } from './verbose.js';
|
|
26
27
|
export async function handleRunCommand(options, command) {
|
|
27
28
|
const parsed = parseRunCommandOptions(command);
|
|
28
29
|
const allOptions = parsed.allOptions;
|
|
@@ -36,13 +37,20 @@ export async function handleRunCommand(options, command) {
|
|
|
36
37
|
const explicitInstruction = parsed.explicitInstruction;
|
|
37
38
|
const jsonSchemaSpec = parsed.jsonSchemaSpec;
|
|
38
39
|
const rawOutputFormat = parsed.rawOutputFormat;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const commonOptions = resolveCliCommonOptions({
|
|
41
|
+
repoPath: runPath,
|
|
42
|
+
verbose: allOptions.verbose,
|
|
43
|
+
outputFormat: rawOutputFormat,
|
|
44
|
+
});
|
|
45
|
+
if (!commonOptions.ok) {
|
|
46
|
+
getLogger().error(commonOptions.message, true);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const outputFormat = commonOptions.options.outputFormat ?? resolveOutputFormat(rawOutputFormat);
|
|
50
|
+
if (!outputFormat) {
|
|
42
51
|
getLogger().error(text.cli.invalidOutputFormat(rawOutputFormat), true);
|
|
43
52
|
process.exit(1);
|
|
44
53
|
}
|
|
45
|
-
const outputFormat = rawOutputFormat;
|
|
46
54
|
const headlessOutput = outputFormat !== 'text';
|
|
47
55
|
const rawOutputProfile = parsed.rawOutputProfile;
|
|
48
56
|
const outputProfileForStreamJson = parsed.outputProfileForStreamJson;
|
|
@@ -167,7 +175,7 @@ export async function handleRunCommand(options, command) {
|
|
|
167
175
|
}
|
|
168
176
|
if ('printedConfig' in configResult)
|
|
169
177
|
return;
|
|
170
|
-
const resolvedConfig = configResult.resolvedConfig;
|
|
178
|
+
const { resolvedConfig, auditScope } = configResult.resolvedConfig;
|
|
171
179
|
const runtimeOptions = await resolveRunRuntimeOptions({
|
|
172
180
|
repoPath: runPath,
|
|
173
181
|
resolvedConfig,
|
|
@@ -253,7 +261,7 @@ export async function handleRunCommand(options, command) {
|
|
|
253
261
|
if (!effectiveVerify) {
|
|
254
262
|
getLogger().warn(text.verify.noCommandFound);
|
|
255
263
|
}
|
|
256
|
-
const verboseLevel =
|
|
264
|
+
const verboseLevel = commonOptions.options.verboseLevel;
|
|
257
265
|
logRunVerboseSummary({
|
|
258
266
|
verboseLevel,
|
|
259
267
|
instruction: instructionText,
|
|
@@ -267,15 +275,6 @@ export async function handleRunCommand(options, command) {
|
|
|
267
275
|
configPath: resolvedConfig.source.used ? resolvedConfig.source.path || '' : undefined,
|
|
268
276
|
});
|
|
269
277
|
try {
|
|
270
|
-
const auditScopeResolution = resolveAuditScope({
|
|
271
|
-
cliValue: allOptions.auditScope,
|
|
272
|
-
configValue: resolvedConfig.observability.audit.scope,
|
|
273
|
-
});
|
|
274
|
-
if (!auditScopeResolution.ok) {
|
|
275
|
-
getLogger().error(text.cli.invalidAuditScope(auditScopeResolution.invalid), true);
|
|
276
|
-
process.exit(1);
|
|
277
|
-
}
|
|
278
|
-
const auditScope = auditScopeResolution.value;
|
|
279
278
|
const { llm } = createRuntimeLlmAndWarn({
|
|
280
279
|
llmConfig: resolvedConfig.llm,
|
|
281
280
|
langfuseEnabled: resolvedConfig.observability.langfuse.enabled,
|
|
@@ -30,6 +30,7 @@ export function buildRunLoopParams(params) {
|
|
|
30
30
|
forceNonInteractive: params.headlessOutput || params.printMode,
|
|
31
31
|
permissionMode: params.permissionMode,
|
|
32
32
|
}),
|
|
33
|
+
permissionMode: params.permissionMode,
|
|
33
34
|
extensions: params.extensions,
|
|
34
35
|
permissionRules: params.permissionRules,
|
|
35
36
|
eventPayload: params.headlessIncludeToolInput ||
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveRepoPath } from '../../utils/resolve-cli-config.js';
|
|
2
2
|
function splitToolRules(raw) {
|
|
3
3
|
const parts = [];
|
|
4
4
|
const push = (s) => {
|
|
@@ -20,7 +20,7 @@ function splitToolRules(raw) {
|
|
|
20
20
|
}
|
|
21
21
|
export function parseRunCommandOptions(command) {
|
|
22
22
|
const allOptions = command.optsWithGlobals();
|
|
23
|
-
const repoPath =
|
|
23
|
+
const repoPath = resolveRepoPath({ repo: allOptions.repo, cwd: process.cwd() });
|
|
24
24
|
const continueSession = Boolean(allOptions.continue);
|
|
25
25
|
const resumeSessionId = typeof allOptions.resume === 'string'
|
|
26
26
|
? allOptions.resume
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
export function resolveOutputFormat(raw) {
|
|
2
|
-
if (raw === 'text' || raw === 'stream-json' || raw === 'json')
|
|
3
|
-
return raw;
|
|
4
|
-
return undefined;
|
|
5
|
-
}
|
|
6
1
|
export function validateRunCommandOptions(params) {
|
|
7
2
|
const { parsed } = params;
|
|
8
3
|
if (parsed.explicitInstruction && parsed.printInstruction) {
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { getLogger } from '../../../core/facades/cli-observability.js';
|
|
2
2
|
import { text } from '../../locales/index.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return 'basic';
|
|
6
|
-
if (typeof raw === 'string')
|
|
7
|
-
return raw;
|
|
8
|
-
return undefined;
|
|
9
|
-
}
|
|
3
|
+
import { resolveVerboseLevel } from '../../utils/verbose-level.js';
|
|
4
|
+
export { resolveVerboseLevel };
|
|
10
5
|
export function logRunVerboseSummary(params) {
|
|
11
6
|
if (!params.verboseLevel)
|
|
12
7
|
return;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { buildA2AAgentCard, buildSidecarRouteDescriptors, createAcpFormalAgent, createAgentServerRuntime, createInteractionFacade, createSalmonTaskExecutor, createTaskEventBus, createPluginRegistry, createPromptRegistry,
|
|
1
|
+
import { buildA2AAgentCard, buildSidecarRouteDescriptors, createAcpFormalAgent, createAgentServerRuntime, createInteractionFacade, createSalmonTaskExecutor, createTaskEventBus, createPluginRegistry, createPromptRegistry, defaultPathAdapter, defaultSidecarRouteCatalog, getSidecarListenOptions, getUserAcpSessionStorePath, GitSnapshotCheckpointService, getLogger, mkdir, PlainReporter, PluginLoader, resolveExtensions, runSalmonLoop, setPluginRegistry, setPromptRegistry, startAcpStdioServer, StderrReporter, } from '../../core/facades/cli-serve.js';
|
|
2
2
|
import { createTerminalAuthorizationProvider } from '../authorization/provider.js';
|
|
3
3
|
import { text } from '../locales/index.js';
|
|
4
|
-
import { resolveAuditScope } from '../utils/audit-scope.js';
|
|
5
4
|
import { createOutcomeReporter } from '../utils/outcome-reporter.js';
|
|
5
|
+
import { resolveCliConfig } from '../utils/resolve-cli-config.js';
|
|
6
6
|
import { createRuntimeLlmAndWarn } from './run/runtime-llm.js';
|
|
7
7
|
function parsePort(value, fallback) {
|
|
8
8
|
if (value === undefined || value === null || value === '')
|
|
@@ -45,18 +45,20 @@ export function registerServeCommands(program) {
|
|
|
45
45
|
}
|
|
46
46
|
export async function handleServeCommand(_options, command) {
|
|
47
47
|
const allOptions = command.optsWithGlobals();
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
const configResult = await resolveCliConfig({
|
|
49
|
+
repo: allOptions.repo,
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
configPath: allOptions.config,
|
|
52
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
53
|
+
auditScope: allOptions.auditScope,
|
|
54
|
+
logMode: allOptions.logMode,
|
|
54
55
|
});
|
|
55
|
-
if (!
|
|
56
|
-
getLogger().error(
|
|
56
|
+
if (!configResult.ok) {
|
|
57
|
+
getLogger().error(configResult.message, true);
|
|
57
58
|
process.exit(1);
|
|
58
59
|
}
|
|
59
|
-
const auditScope =
|
|
60
|
+
const { resolvedConfig, auditScope, repoPath: defaultRepoPath } = configResult;
|
|
61
|
+
const serverConfig = resolvedConfig.server;
|
|
60
62
|
const rawA2aHost = allOptions.a2aHost ?? serverConfig?.a2a?.host;
|
|
61
63
|
const a2aHost = String(rawA2aHost ?? '127.0.0.1');
|
|
62
64
|
const rawA2aPort = allOptions.a2aPort ?? serverConfig?.a2a?.port;
|
|
@@ -113,6 +115,7 @@ export async function handleServeCommand(_options, command) {
|
|
|
113
115
|
langfuseSessionId: resolvedConfig.observability.langfuse.sessionId,
|
|
114
116
|
langfuseUserId: resolvedConfig.observability.langfuse.userId,
|
|
115
117
|
auditScope,
|
|
118
|
+
permissionMode: resolvedConfig.permissionMode,
|
|
116
119
|
languagePlugins,
|
|
117
120
|
fileSystemOverride,
|
|
118
121
|
authorizationProvider: authorizationProvider ?? defaultAuthorizationProvider,
|
|
@@ -228,8 +231,19 @@ export async function handleServeCommand(_options, command) {
|
|
|
228
231
|
}
|
|
229
232
|
export async function handleServeAcpCommand(_options, command) {
|
|
230
233
|
const allOptions = command.optsWithGlobals();
|
|
231
|
-
const
|
|
232
|
-
|
|
234
|
+
const configResult = await resolveCliConfig({
|
|
235
|
+
repo: allOptions.repo,
|
|
236
|
+
cwd: process.cwd(),
|
|
237
|
+
configPath: allOptions.config,
|
|
238
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
239
|
+
auditScope: allOptions.auditScope,
|
|
240
|
+
logMode: allOptions.logMode,
|
|
241
|
+
});
|
|
242
|
+
if (!configResult.ok) {
|
|
243
|
+
getLogger().error(configResult.message, true);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
const { resolvedConfig, auditScope, repoPath: defaultRepoPath } = configResult;
|
|
233
247
|
getLogger().setReporter(allOptions.color === false ? new StderrReporter() : new PlainReporter());
|
|
234
248
|
const languagePlugins = createPluginRegistry();
|
|
235
249
|
setPluginRegistry(languagePlugins);
|
|
@@ -240,14 +254,6 @@ export async function handleServeAcpCommand(_options, command) {
|
|
|
240
254
|
llmConfig: resolvedConfig.llm,
|
|
241
255
|
langfuseEnabled: resolvedConfig.observability.langfuse.enabled,
|
|
242
256
|
});
|
|
243
|
-
const auditScopeResolution = resolveAuditScope({
|
|
244
|
-
cliValue: allOptions.auditScope,
|
|
245
|
-
configValue: resolvedConfig.observability.audit.scope,
|
|
246
|
-
});
|
|
247
|
-
if (!auditScopeResolution.ok) {
|
|
248
|
-
getLogger().error(text.cli.invalidAuditScope(auditScopeResolution.invalid), true);
|
|
249
|
-
process.exit(1);
|
|
250
|
-
}
|
|
251
257
|
const outcomeReporter = createOutcomeReporter({
|
|
252
258
|
enabled: resolvedConfig.observability.langfuse.outcome,
|
|
253
259
|
endpoint: resolvedConfig.observability.langfuse.endpoint,
|
|
@@ -275,7 +281,8 @@ export async function handleServeAcpCommand(_options, command) {
|
|
|
275
281
|
outcomeReporter,
|
|
276
282
|
langfuseSessionId: resolvedConfig.observability.langfuse.sessionId,
|
|
277
283
|
langfuseUserId: resolvedConfig.observability.langfuse.userId,
|
|
278
|
-
auditScope
|
|
284
|
+
auditScope,
|
|
285
|
+
permissionMode: resolvedConfig.permissionMode,
|
|
279
286
|
languagePlugins,
|
|
280
287
|
authorizationProvider: authorizationProvider ?? defaultAuthorizationProvider,
|
|
281
288
|
authorizationMode,
|
package/dist/cli/locales/en.js
CHANGED
|
@@ -35,6 +35,7 @@ export const en = {
|
|
|
35
35
|
chatAnswerEmpty: 'No answer produced.',
|
|
36
36
|
unknownCommand: (cmd) => `Unknown command: ${cmd}. Type /help for available commands.`,
|
|
37
37
|
helpAvailableCommands: (rows) => `Available Commands:\n${rows}`,
|
|
38
|
+
programHelpFooter: '\nTips:\n Use "s8p <command> --help" to see command-specific options.\n In chat, type /help to list slash commands.',
|
|
38
39
|
slashHandlerUnavailable: 'Command handler unavailable',
|
|
39
40
|
slashInternalError: 'Internal error',
|
|
40
41
|
skillNoPrompt: (id) => `Skill ${id} did not produce a prompt`,
|
|
@@ -234,6 +235,7 @@ export const en = {
|
|
|
234
235
|
preflightPolicyOption: 'Preflight policy (lenient: continue on test failure, strict: fail on test failure)',
|
|
235
236
|
checkpointStrategyOption: 'Checkpoint strategy to use (direct, worktree)',
|
|
236
237
|
permissionModeOption: 'Permission mode (interactive, yolo)',
|
|
238
|
+
logModeOption: 'UI log mode (quiet, normal, debug)',
|
|
237
239
|
environmentModeOption: 'Worktree environment mode (strict, parity)',
|
|
238
240
|
applyBackOnDirtyOption: 'Behavior when apply-back detects a dirty workspace (3way, abort)',
|
|
239
241
|
worktreePrepareOption: 'Optional setup command to run inside worktree',
|
|
@@ -8,7 +8,12 @@ export function bootstrapProgram() {
|
|
|
8
8
|
chalk.level = 3;
|
|
9
9
|
const program = new Command();
|
|
10
10
|
program.exitOverride();
|
|
11
|
-
program
|
|
11
|
+
program
|
|
12
|
+
.name('s8p')
|
|
13
|
+
.alias('salmonloop')
|
|
14
|
+
.description(text.cli.programDescription)
|
|
15
|
+
.version('0.2.0')
|
|
16
|
+
.addHelpText('after', text.cli.programHelpFooter);
|
|
12
17
|
return program;
|
|
13
18
|
}
|
|
14
19
|
//# sourceMappingURL=program-bootstrap.js.map
|
|
@@ -90,6 +90,8 @@ export function registerProgramCommands(program) {
|
|
|
90
90
|
.command('context')
|
|
91
91
|
.description(text.cli.contextDescription)
|
|
92
92
|
.option('-i, --instruction <instruction>', text.cli.instructionOption)
|
|
93
|
+
.option('--config <path>', text.cli.configOption)
|
|
94
|
+
.option('--no-config-file', text.cli.noConfigFileOption)
|
|
93
95
|
.option('-f, --file <path>', text.cli.fileOption)
|
|
94
96
|
.option('-s, --selection <text>', text.cli.selectionOption)
|
|
95
97
|
.option('--diff-scope <scope>', text.cli.contextDiffScopeOption, 'primary')
|
|
@@ -100,6 +102,8 @@ export function registerProgramCommands(program) {
|
|
|
100
102
|
program
|
|
101
103
|
.command('chat', { isDefault: true })
|
|
102
104
|
.description('Enter interactive chat mode (default)')
|
|
105
|
+
.option('--config <path>', text.cli.configOption)
|
|
106
|
+
.option('--no-config-file', text.cli.noConfigFileOption)
|
|
103
107
|
.option('--verbose [level]', text.cli.verboseOption)
|
|
104
108
|
.action(handleChatCommand);
|
|
105
109
|
}
|
|
@@ -7,6 +7,7 @@ export function configureGlobalProgramOptions(program) {
|
|
|
7
7
|
.option('--resume <sessionId>', text.cli.resumeOption)
|
|
8
8
|
.option('-v, --verify <command>', text.cli.verifyOption)
|
|
9
9
|
.option('--no-verify', 'Disable verification')
|
|
10
|
+
.option('--log-mode <mode>', text.cli.logModeOption)
|
|
10
11
|
.option('-cs, --checkpoint-strategy <type>', text.cli.checkpointStrategyOption, 'worktree')
|
|
11
12
|
.option('--mode <mode>', text.cli.permissionModeOption, 'interactive')
|
|
12
13
|
.option('--llm-output <kinds>', text.cli.llmOutputOption)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createSlashRegistry, createStandardToolstack, executeSkill, logIgnoredError, getLogger, RuntimeEnvironment, SkillLoader, SlashRouter, } from '../../core/facades/cli-slash-runtime.js';
|
|
2
|
+
import { formatHelpRows } from '../commands/help-format.js';
|
|
2
3
|
import { suggestSubcommands } from '../commands/subcommand-suggestions.js';
|
|
3
4
|
import { text } from '../locales/index.js';
|
|
4
5
|
function isSafeSkillId(id) {
|
|
@@ -63,12 +64,11 @@ export async function createCliSlashRuntime(options) {
|
|
|
63
64
|
const handler = {
|
|
64
65
|
execute: async (_req) => {
|
|
65
66
|
const visible = registry.list().filter((c) => !c.hidden);
|
|
66
|
-
const
|
|
67
|
-
const rows = visible.map((c) => `${c.name}`.padEnd(maxName + 2) + c.description);
|
|
67
|
+
const rows = formatHelpRows(visible);
|
|
68
68
|
options.emit({
|
|
69
69
|
type: 'log',
|
|
70
70
|
level: 'info',
|
|
71
|
-
message: text.cli.helpAvailableCommands(rows
|
|
71
|
+
message: text.cli.helpAvailableCommands(rows),
|
|
72
72
|
timestamp: new Date(),
|
|
73
73
|
});
|
|
74
74
|
return { kind: 'consumed' };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { defaultPathAdapter } from '../../core/adapters/path/path-adapter.js';
|
|
2
|
+
import { ConfigError, normalizeUiLogMode, resolveConfig } from '../../core/config/index.js';
|
|
3
|
+
import { text } from '../locales/index.js';
|
|
4
|
+
import { resolveAuditScope } from './audit-scope.js';
|
|
5
|
+
import { resolveOutputFormat } from './output-format.js';
|
|
6
|
+
import { resolveVerboseLevel } from './verbose-level.js';
|
|
7
|
+
export async function resolveCliConfig(params) {
|
|
8
|
+
const common = resolveCliCommonOptions({
|
|
9
|
+
repoPath: params.repoPath,
|
|
10
|
+
repo: params.repo,
|
|
11
|
+
cwd: params.cwd,
|
|
12
|
+
verbose: params.verbose,
|
|
13
|
+
outputFormat: params.outputFormat,
|
|
14
|
+
});
|
|
15
|
+
if (!common.ok) {
|
|
16
|
+
return { ok: false, message: common.message };
|
|
17
|
+
}
|
|
18
|
+
const { repoPath, verboseLevel, outputFormat, headlessOutput } = common.options;
|
|
19
|
+
let resolvedConfig;
|
|
20
|
+
try {
|
|
21
|
+
resolvedConfig = await resolveConfig({
|
|
22
|
+
repoRoot: repoPath,
|
|
23
|
+
configFilePath: params.configPath,
|
|
24
|
+
enableConfigFile: params.enableConfigFile !== false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
if (err instanceof ConfigError) {
|
|
29
|
+
return {
|
|
30
|
+
ok: false,
|
|
31
|
+
message: text.config.error(err.code || err.message, err.details),
|
|
32
|
+
errorCode: err.code,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36
|
+
return { ok: false, message: text.config.loadFailed(msg) };
|
|
37
|
+
}
|
|
38
|
+
const auditScopeResolution = resolveAuditScope({
|
|
39
|
+
cliValue: params.auditScope,
|
|
40
|
+
configValue: resolvedConfig.observability.audit.scope,
|
|
41
|
+
});
|
|
42
|
+
if (!auditScopeResolution.ok) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
message: text.cli.invalidAuditScope(auditScopeResolution.invalid),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (params.logMode !== undefined) {
|
|
49
|
+
const normalized = normalizeUiLogMode(params.logMode);
|
|
50
|
+
if (!normalized) {
|
|
51
|
+
return { ok: false, message: text.cli.logModeInvalid(String(params.logMode)) };
|
|
52
|
+
}
|
|
53
|
+
resolvedConfig = {
|
|
54
|
+
...resolvedConfig,
|
|
55
|
+
ui: {
|
|
56
|
+
...resolvedConfig.ui,
|
|
57
|
+
logMode: normalized,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
repoPath,
|
|
64
|
+
verboseLevel,
|
|
65
|
+
outputFormat,
|
|
66
|
+
headlessOutput,
|
|
67
|
+
resolvedConfig,
|
|
68
|
+
auditScope: auditScopeResolution.value,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function resolveRepoPath(params) {
|
|
72
|
+
return defaultPathAdapter.resolve(params.repo || params.cwd || process.cwd());
|
|
73
|
+
}
|
|
74
|
+
export function resolveCliCommonOptions(params) {
|
|
75
|
+
const repoPath = params.repoPath ?? resolveRepoPath({ repo: params.repo, cwd: params.cwd });
|
|
76
|
+
const verboseLevel = resolveVerboseLevel(params.verbose);
|
|
77
|
+
let outputFormat;
|
|
78
|
+
let headlessOutput;
|
|
79
|
+
if (params.outputFormat !== undefined) {
|
|
80
|
+
const raw = String(params.outputFormat || '');
|
|
81
|
+
const resolved = resolveOutputFormat(raw);
|
|
82
|
+
if (!resolved) {
|
|
83
|
+
return { ok: false, message: text.cli.invalidOutputFormat(raw) };
|
|
84
|
+
}
|
|
85
|
+
outputFormat = resolved;
|
|
86
|
+
headlessOutput = resolved !== 'text';
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
options: {
|
|
91
|
+
repoPath,
|
|
92
|
+
verboseLevel,
|
|
93
|
+
outputFormat,
|
|
94
|
+
headlessOutput,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=resolve-cli-config.js.map
|