@nextxai/cli 0.3.2 → 0.3.4
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 +9 -0
- package/dist/auth/credentials.js +1 -1
- package/dist/commands/ai.js +6 -6
- package/dist/commands/ci-policy.js +2 -2
- package/dist/commands/ci.js +2 -2
- package/dist/core/i18n.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.4
|
|
4
|
+
|
|
5
|
+
- Every file in a GitHub release now has a signed build provenance attestation: `gh attestation verify <file> --repo <owner/repo>`. Release notes list the install commands and how to verify a download.
|
|
6
|
+
- Security reports go through GitHub's private vulnerability reporting on this repository.
|
|
7
|
+
|
|
8
|
+
## 0.3.3
|
|
9
|
+
|
|
10
|
+
- Maintenance release: tidier source comments, no change in behaviour.
|
|
11
|
+
|
|
3
12
|
## 0.3.2
|
|
4
13
|
|
|
5
14
|
- `tools list`, the MCP sign-in and help examples follow the modules your product offers.
|
package/dist/auth/credentials.js
CHANGED
|
@@ -99,7 +99,7 @@ function loadKeyring() {
|
|
|
99
99
|
/**
|
|
100
100
|
* Each backend owns its own keychain items. Sharing one item between the addon (process "node") and the OS tool
|
|
101
101
|
* (`security`) makes macOS move the item's access list to whoever wrote last, and every read by the other one
|
|
102
|
-
* then pops a password dialog
|
|
102
|
+
* then pops a password dialog — several stacked dialogs when calls overlap.
|
|
103
103
|
*/
|
|
104
104
|
let osTool = false;
|
|
105
105
|
const service = () => `${brand().bin}-cli${osTool ? "-os" : ""}`;
|
package/dist/commands/ai.js
CHANGED
|
@@ -87,17 +87,17 @@ export function proposalCard(a) {
|
|
|
87
87
|
* Rules (docs §2.6): read mode never writes; finance never from the terminal; no TTY ⇒ never;
|
|
88
88
|
* large writes need the typed number; auto mode skips the y/N for normal writes only.
|
|
89
89
|
*/
|
|
90
|
-
/**
|
|
90
|
+
/** A `login --ci` session has nobody to press confirm: the server decides from the pre-approval policy (`ci policy`). */
|
|
91
91
|
async function isCiSession() {
|
|
92
92
|
const { currentAuth } = await import("../auth/session.js");
|
|
93
93
|
const a = await currentAuth().catch(() => undefined);
|
|
94
94
|
return a?.kind === "session" && a.session.via === "ci";
|
|
95
95
|
}
|
|
96
|
-
/**
|
|
96
|
+
/** Command a person runs to confirm later: reopen the conversation, or confirm by proposal id where the platform supports it. */
|
|
97
97
|
function confirmHint(nonce, conversationId) {
|
|
98
98
|
return `${brand().bin} -r ${conversationId}`;
|
|
99
99
|
}
|
|
100
|
-
/** 403
|
|
100
|
+
/** A 403 from the CI write gate means nothing was written and the proposal still waits for a person — report it, not as a crash. */
|
|
101
101
|
function ciDenied(e) {
|
|
102
102
|
const err = e;
|
|
103
103
|
return err instanceof CliError && err.exitCode === Exit.forbidden ? err.message : undefined;
|
|
@@ -108,7 +108,7 @@ export async function handleProposal(sessionId, a, mode = context().mode) {
|
|
|
108
108
|
return { written: false, message: r.message };
|
|
109
109
|
}
|
|
110
110
|
const risk = riskOf(a);
|
|
111
|
-
//
|
|
111
|
+
// On the default platform a proposal is confirmed by reopening the conversation.
|
|
112
112
|
let resume = `${brand().bin} -r ${sessionId}`;
|
|
113
113
|
if (mode === "read") {
|
|
114
114
|
info(c.dim(tr(" Chế độ chỉ đọc: không ghi. Đổi chế độ: --mode propose", " Read-only mode: nothing written. Switch with --mode propose")));
|
|
@@ -121,7 +121,7 @@ export async function handleProposal(sessionId, a, mode = context().mode) {
|
|
|
121
121
|
return { written: false };
|
|
122
122
|
}
|
|
123
123
|
if (!hasTty()) {
|
|
124
|
-
// CI + --mode auto:
|
|
124
|
+
// CI + --mode auto: send the confirmation; the server writes only within this repository's pre-approval policy (ci policy).
|
|
125
125
|
if (brand().platform === "nextx" && mode === "auto" && (await isCiSession())) {
|
|
126
126
|
try {
|
|
127
127
|
const r = await confirmAction(sessionId, a);
|
|
@@ -287,7 +287,7 @@ async function printAsk(o, question, piped) {
|
|
|
287
287
|
const risk = proposal ? riskOf(proposal) : undefined;
|
|
288
288
|
const allowedRisk = context().mode !== "read" && risk !== "finance" && risk !== "device";
|
|
289
289
|
let applied;
|
|
290
|
-
//
|
|
290
|
+
// CI session with --mode auto: send the confirmation; the server writes only within a pre-approval policy (403 = not written, with the reason).
|
|
291
291
|
if (!applied && proposal?.writes && brand().platform === "nextx" && allowedRisk && context().mode === "auto" && !hasTty() && (await isCiSession()))
|
|
292
292
|
applied = await confirmAction(conversationId, proposal).then((r) => ({ written: r.success, message: r.message }), (e) => {
|
|
293
293
|
const why = ciDenied(e);
|
|
@@ -8,7 +8,7 @@ import { context } from "../core/context.js";
|
|
|
8
8
|
import { requirePerson } from "../auth/session.js";
|
|
9
9
|
import { parseDuration } from "./keys.js";
|
|
10
10
|
const BASE = "/ai/ci-write-policies";
|
|
11
|
-
//
|
|
11
|
+
// Examples and the approval screen differ per platform: some write by entry kind, others by permission code.
|
|
12
12
|
const exampleKinds = () => brand().examples.ciKinds;
|
|
13
13
|
function approvePlace() {
|
|
14
14
|
return tr("Thiết lập › Ứng dụng & API › CI", "Settings › Apps & API › CI");
|
|
@@ -25,7 +25,7 @@ function stateLabel(s) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
async function findPolicy(id) {
|
|
28
|
-
//
|
|
28
|
+
// UUID v7 ids share their first characters (time prefix), so the table shows the LAST 8 and lookup matches either end.
|
|
29
29
|
const all = (await get(BASE)).items;
|
|
30
30
|
const hits = all.filter((x) => x.id === id || x.id.startsWith(id) || x.id.endsWith(id));
|
|
31
31
|
if (hits.length > 1)
|
package/dist/commands/ci.js
CHANGED
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
- run: npx -y ${b.pkg} login --ci --workspace ${ws}
|
|
28
28
|
- run: npx -y ${b.pkg} -p "${tr(b.example.vi, b.example.en)}" --json > report.json`;
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
30
|
+
/** Sample CI job that writes: works once an admin approves a pre-approval policy (`ci policy request`). */
|
|
31
31
|
export function workflowWriteSample(repo = "acme/web", ws = "my-workspace") {
|
|
32
32
|
const b = brand();
|
|
33
33
|
return `# .github/workflows/follow-up.yml (${repo})
|
|
@@ -87,7 +87,7 @@ export function registerCi(program) {
|
|
|
87
87
|
await post(`/iam/ci-trusts/${t.id}/revoke`, {});
|
|
88
88
|
ok(tr("Đã thu hồi.", "Revoked."));
|
|
89
89
|
});
|
|
90
|
-
//
|
|
90
|
+
// Pre-approval policies: the same /ai/ci-write-policies contract on every platform.
|
|
91
91
|
registerCiPolicy(ci);
|
|
92
92
|
ci.command("example").description(tr("in mẫu workflow GitHub Actions", "print a sample GitHub Actions workflow"))
|
|
93
93
|
.option("--repo <owner/repo>").option("--workspace <code>")
|
package/dist/core/i18n.js
CHANGED
|
@@ -84,7 +84,7 @@ export function t(key, vars = {}) {
|
|
|
84
84
|
const all = { bin: b.bin, prefix: b.envPrefix, name: b.name, ...vars };
|
|
85
85
|
return (dict[key] ?? vi[key] ?? key).replace(/\{(\w+)\}/g, (_, k) => String(all[k] ?? `{${k}}`));
|
|
86
86
|
}
|
|
87
|
-
/** Inline bilingual helper for one-off strings: tr(
|
|
87
|
+
/** Inline bilingual helper for one-off strings: tr(vietnamese, english). */
|
|
88
88
|
export function tr(viText, enText) {
|
|
89
89
|
return currentLang() === "en" ? enText : viText;
|
|
90
90
|
}
|