@corvio/cli 0.1.0-beta.16 → 0.1.0-beta.17
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.js +108 -64
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
agentCredentialPath,
|
|
40
40
|
} from "./core.js";
|
|
41
41
|
|
|
42
|
-
const VERSION = "0.1.0-beta.
|
|
42
|
+
const VERSION = "0.1.0-beta.17";
|
|
43
43
|
const DEFAULT_API_BASE = "https://api.corvio.ai/v1";
|
|
44
44
|
const DEFAULT_APP_BASE = "https://corvio.ai";
|
|
45
45
|
const USER_AGENT = `corvio-cli/${VERSION}`;
|
|
@@ -72,6 +72,7 @@ const COMMAND_OPTIONS = Object.freeze({
|
|
|
72
72
|
"ask:": [
|
|
73
73
|
"prompt", "conversation-id", "sources", "allow-actions", "context-file", "idempotency-key",
|
|
74
74
|
"processing-profile", "max-processing-profile", "scan-mode", "skills-extraction-mode", "caller-model",
|
|
75
|
+
"file", "asset-ids", "mime-type",
|
|
75
76
|
],
|
|
76
77
|
"agents:list": ["include-revoked"],
|
|
77
78
|
"agents:connect": [
|
|
@@ -140,7 +141,7 @@ Usage:
|
|
|
140
141
|
corvio workspaces list|use|current|create [id]
|
|
141
142
|
corvio capabilities
|
|
142
143
|
corvio collaboration status [--project <path>] [--provider codex|claude_code|copilot]
|
|
143
|
-
corvio ask --prompt <text> [--conversation-id <id>] [--allow-actions] [--processing-profile auto|economy|standard|deep]
|
|
144
|
+
corvio ask --prompt <text> [--file <path>] [--asset-ids <id,id>] [--conversation-id <id>] [--allow-actions] [--processing-profile auto|economy|standard|deep]
|
|
144
145
|
corvio agents list|connect|create|update|rotate [id]
|
|
145
146
|
corvio agent claim|renew|complete|fail|comments|comment|reply|status|closeout|run [id]
|
|
146
147
|
corvio questions list|get [id]
|
|
@@ -169,7 +170,7 @@ const COMMAND_HELP = Object.freeze({
|
|
|
169
170
|
workspaces: `Usage:\n corvio workspaces list\n corvio workspaces use <workspace-id>\n corvio workspaces current\n corvio workspaces create --name <name> [--kind personal|team]\n\nWorkspace status and blocked capability reasons are returned with each item.`,
|
|
170
171
|
capabilities: `Usage: corvio capabilities [--json]\n\nShow live API resources, principal scopes, selected Workspace status, and CLI compatibility.`,
|
|
171
172
|
collaboration: `Usage:\n corvio collaboration status [--project <path>] [--provider codex|claude_code|copilot]\n\nVerify that the current project has a bound Corvio Agent, the official collaboration Skill is discoverable at the live contract version, and the inbound listener state is reported separately. This is the foreground work-loop readiness check; a listening process alone is not enough.`,
|
|
172
|
-
ask: `Usage: corvio ask --prompt <text> [--conversation-id <id>] [--sources workspace,web,memory] [--allow-actions] [--processing-profile auto|economy|standard|deep] [--max-processing-profile economy|standard|deep] [--scan-mode auto|always|off] [--skills-extraction-mode auto|always|off] [--caller-model <host-model>] [--context-file <json>] [--idempotency-key <key>]\n\
|
|
173
|
+
ask: `Usage: corvio ask --prompt <text> [--file <path>] [--asset-ids <id,id>] [--conversation-id <id>] [--sources workspace,web,memory] [--allow-actions] [--processing-profile auto|economy|standard|deep] [--max-processing-profile economy|standard|deep] [--scan-mode auto|always|off] [--skills-extraction-mode auto|always|off] [--caller-model <host-model>] [--context-file <json>] [--idempotency-key <key>]\n\n--file retains the selected local file, verifies its hash, and attaches the finalized Asset to this exact question. --asset-ids attaches already-retained Corvio Assets. Skill extraction mode always requires --allow-actions; answer-only questions may use auto or off.`,
|
|
173
174
|
agents: `Usage:\n corvio agents list\n corvio agents connect [--provider codex|claude_code|copilot] [--project <path>] [--permission-profile read_only|workspace_write|danger_full_access] [--trigger-policy owner_only|workspace_members] [--display-name <name>] [--recover-credential] [--no-listen]\n corvio agents create --handle <handle> --display-name <name> [--provider codex|claude_code|copilot|custom] [--permissions read,comment,edit]\n corvio agents update <id> [--display-name <name>] [--status active|paused|revoked] [--permissions <list>]\n corvio agents rotate <id>\n\n'connect' binds the current Git project (or --project path) to one stable personal Agent. Repeating it is idempotent; another project creates another Agent. It reports provider/CLI, listener, and foreground Skill readiness separately; run corvio collaboration status after installing or refreshing the Skill. The default workspace_write profile is limited by the provider's native sandbox. owner_only is the safe trigger default. Secrets and absolute project paths stay local.`,
|
|
174
175
|
agent: `Usage:\n corvio agent claim [--worker-id <id>] [--wait-seconds <0-30>]\n corvio agent renew <event-id> --lease-token <token> [--lease-seconds <30-900>]\n corvio agent complete <event-id> --lease-token <token> [--result-file <json>]\n corvio agent fail <event-id> --lease-token <token> --error <message>\n corvio agent mentions --document-id <id> [--query <name>]\n corvio agent comments --document-id <id>\n corvio agent comment --document-id <id> --body <text> [--selection-file <json>] [--start-new-chain] [--idempotency-key <key>]\n corvio agent reply <thread-id> --document-id <id> --body <text> [--source-event-id <id> --source-event-lease-token <token>|--start-new-chain] [--idempotency-key <key>]\n corvio agent status <thread-id> --document-id <id> --status open|resolved\n corvio agent closeout --document-id <id> [--thread-id <id>] --body <verified-result> [--status open|resolved] [--idempotency-key <key>]\n corvio agent run [--provider codex|claude_code|copilot|custom] [--handler <executable>] [--agent <id>] [--once] [--processing-profile auto|economy|standard|deep] [--max-processing-profile economy|standard|deep] [--scan-mode auto|always|off] [--skills-extraction-mode auto|always|off] [--caller-model <host-model>]\n\nUse mentions before commenting when the target is uncertain; aliases resolve to stable user or Agent IDs and ambiguity fails closed. Use closeout when a Corvio document or comment owned the task: it returns the verified result to that surface and reads document/comments back. Agent-to-Agent comments require either a claimed source event or explicit --start-new-chain. The runner iteratively exchanges origin-scoped evidence with Corvio Query/Writer, then invokes the bound provider inside its local project. Local code changes use the recorded provider permission profile; complex Corvio document changes belong to Query/Writer. Provider children never receive Corvio credentials.`,
|
|
175
176
|
questions: `Usage:\n corvio questions list [--limit <n>] [--cursor <cursor>] [--conversation-id <id>]\n corvio questions get <question-id>`,
|
|
@@ -906,25 +907,52 @@ async function ask(options, positionals) {
|
|
|
906
907
|
code: "skills_extraction_requires_actions",
|
|
907
908
|
});
|
|
908
909
|
}
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
910
|
+
const attachedAssets = [];
|
|
911
|
+
if (options.file) {
|
|
912
|
+
attachedAssets.push(await uploadWorkspaceFile(api, options.file, options["mime-type"]));
|
|
913
|
+
}
|
|
914
|
+
const assetIds = listOption(options, "asset-ids", []);
|
|
915
|
+
for (const asset of attachedAssets) assetIds.push(String(asset.id));
|
|
916
|
+
const uniqueAssetIds = [...new Set(assetIds.map((value) => String(value).trim()).filter(Boolean))];
|
|
917
|
+
let result;
|
|
918
|
+
try {
|
|
919
|
+
result = await api.request("/questions", {
|
|
920
|
+
method: "POST",
|
|
921
|
+
headers: {
|
|
922
|
+
"idempotency-key": idempotencyKey(options),
|
|
923
|
+
...(options["caller-model"] ? { "x-corvio-caller-model": String(options["caller-model"]) } : {}),
|
|
924
|
+
},
|
|
925
|
+
body: {
|
|
926
|
+
prompt,
|
|
927
|
+
conversation_id: options["conversation-id"] || null,
|
|
928
|
+
asset_ids: uniqueAssetIds,
|
|
929
|
+
mode: options["allow-actions"] ? "allow_actions" : "answer_only",
|
|
930
|
+
sources: listOption(options, "sources", ["workspace", "web", "memory"]),
|
|
931
|
+
processing_profile: processingProfile,
|
|
932
|
+
max_processing_profile: maxProcessingProfile,
|
|
933
|
+
scan_mode: scanMode,
|
|
934
|
+
skills_extraction_mode: skillsExtractionMode,
|
|
935
|
+
context,
|
|
936
|
+
},
|
|
937
|
+
timeoutMs: 330_000,
|
|
938
|
+
});
|
|
939
|
+
} catch (error) {
|
|
940
|
+
if (attachedAssets.length > 0) {
|
|
941
|
+
throw new CliError(
|
|
942
|
+
`The selected file was retained as Corvio Asset ${attachedAssets[0].id}, but the question did not complete. Retry with --asset-ids ${attachedAssets.map((asset) => asset.id).join(",")}.`,
|
|
943
|
+
{
|
|
944
|
+
code: "question_failed_after_file_retention",
|
|
945
|
+
exitCode: error instanceof CliError ? error.exitCode : EXIT.REMOTE,
|
|
946
|
+
status: error instanceof CliError ? error.status : null,
|
|
947
|
+
details: {
|
|
948
|
+
asset_ids: attachedAssets.map((asset) => asset.id),
|
|
949
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
throw error;
|
|
955
|
+
}
|
|
928
956
|
const conversationId = String(result?.conversation_id || result?.data?.conversation_id || "").trim();
|
|
929
957
|
if (conversationId && execution.selection?.workspaceId) {
|
|
930
958
|
await storeConversationRoutingReceipt({
|
|
@@ -934,7 +962,14 @@ async function ask(options, positionals) {
|
|
|
934
962
|
apiBase: baseUrl(options),
|
|
935
963
|
});
|
|
936
964
|
}
|
|
937
|
-
writeResult(
|
|
965
|
+
writeResult(
|
|
966
|
+
{
|
|
967
|
+
...result,
|
|
968
|
+
...(attachedAssets.length > 0 ? { attached_assets: attachedAssets } : {}),
|
|
969
|
+
routing: execution.routing,
|
|
970
|
+
},
|
|
971
|
+
{ json: options.json },
|
|
972
|
+
);
|
|
938
973
|
}
|
|
939
974
|
|
|
940
975
|
function enumOption(options, name, allowed, fallback) {
|
|
@@ -2839,6 +2874,51 @@ function mimeTypeFor(path) {
|
|
|
2839
2874
|
})[extension] || "application/octet-stream";
|
|
2840
2875
|
}
|
|
2841
2876
|
|
|
2877
|
+
async function uploadWorkspaceFile(api, inputPath, mimeTypeOverride) {
|
|
2878
|
+
const input = resolve(String(inputPath));
|
|
2879
|
+
const info = await stat(input);
|
|
2880
|
+
if (!info.isFile()) throw new CliError("--file must point to a regular file.", { code: "upload_file_invalid" });
|
|
2881
|
+
if (info.size < 1 || info.size > MAX_UPLOAD_BYTES) {
|
|
2882
|
+
throw new CliError(`--file must be between 1 byte and ${MAX_UPLOAD_BYTES} bytes.`, {
|
|
2883
|
+
code: "upload_file_size_invalid",
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
const bytes = await readFile(input);
|
|
2887
|
+
if (bytes.length < 1 || bytes.length > MAX_UPLOAD_BYTES) {
|
|
2888
|
+
throw new CliError(`--file must be between 1 byte and ${MAX_UPLOAD_BYTES} bytes.`, {
|
|
2889
|
+
code: "upload_file_size_invalid",
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
const fileName = basename(input);
|
|
2893
|
+
const mimeType = String(mimeTypeOverride || mimeTypeFor(input));
|
|
2894
|
+
const initialized = await api.request("/files/uploads", {
|
|
2895
|
+
method: "POST",
|
|
2896
|
+
body: { file_name: fileName, mime_type: mimeType, size_bytes: bytes.length },
|
|
2897
|
+
});
|
|
2898
|
+
await api.putUrl(initialized.upload_url, bytes, {
|
|
2899
|
+
headers: initialized.upload_headers || {},
|
|
2900
|
+
timeoutMs: 5 * 60_000,
|
|
2901
|
+
});
|
|
2902
|
+
const result = await api.request("/files/uploads:finalize", {
|
|
2903
|
+
method: "POST",
|
|
2904
|
+
retrySafe: true,
|
|
2905
|
+
body: {
|
|
2906
|
+
upload_id: initialized.upload_id,
|
|
2907
|
+
blob_name: initialized.blob_name,
|
|
2908
|
+
file_name: fileName,
|
|
2909
|
+
mime_type: mimeType,
|
|
2910
|
+
size_bytes: bytes.length,
|
|
2911
|
+
},
|
|
2912
|
+
});
|
|
2913
|
+
if (result.content_sha256 && result.content_sha256 !== sha256(bytes)) {
|
|
2914
|
+
throw new CliError("Uploaded file content did not match Corvio's SHA-256 receipt.", {
|
|
2915
|
+
code: "upload_integrity_mismatch",
|
|
2916
|
+
exitCode: EXIT.REMOTE,
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
return result;
|
|
2920
|
+
}
|
|
2921
|
+
|
|
2842
2922
|
async function files(options, action, id) {
|
|
2843
2923
|
const { api } = await executionClient(options);
|
|
2844
2924
|
const assetId = id || options.id;
|
|
@@ -2861,47 +2941,11 @@ async function files(options, action, id) {
|
|
|
2861
2941
|
const written = await writeBinaryFile(output, bytes);
|
|
2862
2942
|
result = { ...metadata, output: written };
|
|
2863
2943
|
} else if (action === "upload") {
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
code: "upload_file_size_invalid",
|
|
2870
|
-
});
|
|
2871
|
-
}
|
|
2872
|
-
const bytes = await readFile(input);
|
|
2873
|
-
if (bytes.length < 1 || bytes.length > MAX_UPLOAD_BYTES) {
|
|
2874
|
-
throw new CliError(`--file must be between 1 byte and ${MAX_UPLOAD_BYTES} bytes.`, {
|
|
2875
|
-
code: "upload_file_size_invalid",
|
|
2876
|
-
});
|
|
2877
|
-
}
|
|
2878
|
-
const fileName = basename(input);
|
|
2879
|
-
const mimeType = String(options["mime-type"] || mimeTypeFor(input));
|
|
2880
|
-
const initialized = await api.request("/files/uploads", {
|
|
2881
|
-
method: "POST",
|
|
2882
|
-
body: { file_name: fileName, mime_type: mimeType, size_bytes: bytes.length },
|
|
2883
|
-
});
|
|
2884
|
-
await api.putUrl(initialized.upload_url, bytes, {
|
|
2885
|
-
headers: initialized.upload_headers || {},
|
|
2886
|
-
timeoutMs: 5 * 60_000,
|
|
2887
|
-
});
|
|
2888
|
-
result = await api.request("/files/uploads:finalize", {
|
|
2889
|
-
method: "POST",
|
|
2890
|
-
retrySafe: true,
|
|
2891
|
-
body: {
|
|
2892
|
-
upload_id: initialized.upload_id,
|
|
2893
|
-
blob_name: initialized.blob_name,
|
|
2894
|
-
file_name: fileName,
|
|
2895
|
-
mime_type: mimeType,
|
|
2896
|
-
size_bytes: bytes.length,
|
|
2897
|
-
},
|
|
2898
|
-
});
|
|
2899
|
-
if (result.content_sha256 && result.content_sha256 !== sha256(bytes)) {
|
|
2900
|
-
throw new CliError("Uploaded file content did not match Corvio's SHA-256 receipt.", {
|
|
2901
|
-
code: "upload_integrity_mismatch",
|
|
2902
|
-
exitCode: EXIT.REMOTE,
|
|
2903
|
-
});
|
|
2904
|
-
}
|
|
2944
|
+
result = await uploadWorkspaceFile(
|
|
2945
|
+
api,
|
|
2946
|
+
option(options, "file", { required: true }),
|
|
2947
|
+
options["mime-type"],
|
|
2948
|
+
);
|
|
2905
2949
|
if (options.organize) {
|
|
2906
2950
|
requireConfirmation(options, "Starting semantic organization for the uploaded file");
|
|
2907
2951
|
const organization = await api.request(`/files/${resourcePath(result.id)}:organize`, {
|