@kybernesis/vault 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { listVaultTool, fillFromVaultTool } from "./tools.js";
2
2
  export { VAULT_INSTRUCTIONS } from "./instructions.js";
3
3
  export { listItems, materialize, personFromContext, sameSite, valuesOf, NO_PERSON, type MaterializedItem, type PrincipalContext, type VaultClientOptions, type VaultKind, type VaultSummary, } from "./client.js";
4
+ export { vaultItemAsk, interpretVaultAnswer, vaultItemPrompt, parseVaultItemPrompt, savedAnswer, REQUEST_VAULT_ITEM_DESCRIPTION, VAULT_ITEM_MARKER, SAVED_PREFIX, type VaultItemAsk, type VaultRequestOutcome } from "./request.js";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { listVaultTool, fillFromVaultTool } from "./tools.js";
2
2
  export { VAULT_INSTRUCTIONS } from "./instructions.js";
3
3
  export { listItems, materialize, personFromContext, sameSite, valuesOf, NO_PERSON, } from "./client.js";
4
+ export { vaultItemAsk, interpretVaultAnswer, vaultItemPrompt, parseVaultItemPrompt, savedAnswer, REQUEST_VAULT_ITEM_DESCRIPTION, VAULT_ITEM_MARKER, SAVED_PREFIX } from "./request.js";
@@ -1 +1 @@
1
- export declare const VAULT_INSTRUCTIONS = "## The person's vault\n\nThe person can save logins, cards and addresses in KYBER Studio (Settings \u2192 Vault). You can use them on your own computer without ever seeing them:\n\n- `list_vault` with the page URL tells you what applies: labels, usernames, a card's brand and last four. That is all you get.\n- `fill_from_vault` types an item into the form you are looking at. You give the item id and the CSS selector of each field; the values go straight into the page. Then take a screenshot and check before submitting.\n\nRules: a login only fills on the site it was saved for; if the tool refuses, say so rather than retyping anything by hand. A card asks the person for approval every time. If a site asks for a code or a second factor, stop and tell the person what is on the screen \u2014 they can take over your screen. Never ask the person to paste a password into chat; point them to the vault instead.\n";
1
+ export declare const VAULT_INSTRUCTIONS = "## The person's vault\n\nThe person can save logins, cards and addresses in KYBER Studio (Settings \u2192 Vault). You can use them on your own computer without ever seeing them:\n\n- `list_vault` with the page URL tells you what applies: labels, usernames, a card's brand and last four. That is all you get.\n- `fill_from_vault` types an item into the form you are looking at. You give the item id and the CSS selector of each field; the values go straight into the page. Then take a screenshot and check before submitting.\n\n- When `list_vault` has nothing for the site, call `request_vault_item` with the kind, the site and what you are doing. The turn pauses. If it comes back `saved`, call `fill_from_vault` with the item id. If `manual`, the person is typing on your screen: watch with screenshots and continue once the form is filled, without touching the fields. If `cancelled`, stop.\n\nRules: a login only fills on the site it was saved for; if the tool refuses, say so rather than retyping anything by hand. A card asks the person for approval every time. If a site asks for a code or a second factor, stop and tell the person what is on the screen \u2014 they can take over your screen. Never ask the person to paste a password into chat; point them to the vault instead.\n";
@@ -5,5 +5,7 @@ The person can save logins, cards and addresses in KYBER Studio (Settings → Va
5
5
  - \`list_vault\` with the page URL tells you what applies: labels, usernames, a card's brand and last four. That is all you get.
6
6
  - \`fill_from_vault\` types an item into the form you are looking at. You give the item id and the CSS selector of each field; the values go straight into the page. Then take a screenshot and check before submitting.
7
7
 
8
+ - When \`list_vault\` has nothing for the site, call \`request_vault_item\` with the kind, the site and what you are doing. The turn pauses. If it comes back \`saved\`, call \`fill_from_vault\` with the item id. If \`manual\`, the person is typing on your screen: watch with screenshots and continue once the form is filled, without touching the fields. If \`cancelled\`, stop.
9
+
8
10
  Rules: a login only fills on the site it was saved for; if the tool refuses, say so rather than retyping anything by hand. A card asks the person for approval every time. If a site asks for a code or a second factor, stop and tell the person what is on the screen — they can take over your screen. Never ask the person to paste a password into chat; point them to the vault instead.
9
11
  `;
@@ -0,0 +1,65 @@
1
+ import type { VaultKind } from "./client.js";
2
+ /**
3
+ * A structured question a client can render as a form.
4
+ *
5
+ * eve's `ctx.ask` carries a prompt and options; nothing else. So the first
6
+ * line of the prompt is a marker a Kybernesis client recognises
7
+ * (`[kyb:vault-item] {json}`) and the rest is the plain question every other
8
+ * surface shows. Studio draws a form and answers with the saved item's id;
9
+ * iMessage shows the text and two buttons. The secret never reaches this
10
+ * tool: the client stores it in the control plane itself and hands back an id.
11
+ */
12
+ export declare const VAULT_ITEM_MARKER = "[kyb:vault-item]";
13
+ export interface VaultItemAsk {
14
+ readonly kind: VaultKind;
15
+ readonly site?: string;
16
+ readonly label?: string;
17
+ readonly reason?: string;
18
+ /** Which fields the page wants, when the agent can tell (e.g. ["username","password"] or ["number","cvc","expiration","name"]). */
19
+ readonly fields?: readonly string[];
20
+ }
21
+ export declare function vaultItemPrompt(ask: VaultItemAsk): string;
22
+ /** The marker's payload, if a prompt carries one. Clients call this. */
23
+ export declare function parseVaultItemPrompt(prompt: string): {
24
+ ask: VaultItemAsk;
25
+ text: string;
26
+ } | null;
27
+ /** A client that saved the item answers with this; the tool reads the id out of it. */
28
+ export declare const SAVED_PREFIX = "vault:";
29
+ export declare function savedAnswer(itemId: string): string;
30
+ export type VaultRequestOutcome = {
31
+ status: "saved";
32
+ item_id: string;
33
+ note: string;
34
+ } | {
35
+ status: "manual";
36
+ note: string;
37
+ } | {
38
+ status: "cancelled";
39
+ note: string;
40
+ } | {
41
+ status: "unavailable";
42
+ note: string;
43
+ };
44
+ /** What the agent's tool file passes to `ctx.ask`. The tool itself must be authored in `agent/tools/` — eve compiles `"use workflow"` from source, so a package cannot ship it. */
45
+ export declare function vaultItemAsk(input: VaultItemAsk): {
46
+ prompt: string;
47
+ display: "select";
48
+ allowFreeform: boolean;
49
+ options: ({
50
+ id: string;
51
+ label: string;
52
+ style?: undefined;
53
+ } | {
54
+ id: string;
55
+ label: string;
56
+ style: "danger";
57
+ })[];
58
+ };
59
+ /** Turn the person's answer into the tool's result. */
60
+ export declare function interpretVaultAnswer(answer: {
61
+ status: string;
62
+ optionId?: string;
63
+ text?: string;
64
+ }): VaultRequestOutcome;
65
+ export declare const REQUEST_VAULT_ITEM_DESCRIPTION = "Ask the person for a login, card, address or contact you need but could not find in their vault (use list_vault first). The turn pauses until they answer. They can add it to the vault (you get an item id to use with fill_from_vault), take over your screen to type it themselves, or cancel. Never ask for secrets in chat; use this.";
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A structured question a client can render as a form.
3
+ *
4
+ * eve's `ctx.ask` carries a prompt and options; nothing else. So the first
5
+ * line of the prompt is a marker a Kybernesis client recognises
6
+ * (`[kyb:vault-item] {json}`) and the rest is the plain question every other
7
+ * surface shows. Studio draws a form and answers with the saved item's id;
8
+ * iMessage shows the text and two buttons. The secret never reaches this
9
+ * tool: the client stores it in the control plane itself and hands back an id.
10
+ */
11
+ export const VAULT_ITEM_MARKER = "[kyb:vault-item]";
12
+ export function vaultItemPrompt(ask) {
13
+ const what = ask.kind === "login" ? "a login" : ask.kind === "card" ? "a card" : ask.kind === "address" ? "an address" : "contact details";
14
+ const where = ask.site ? ` for ${ask.site}` : "";
15
+ const why = ask.reason ? ` ${ask.reason.trim().replace(/\.?$/, ".")}` : "";
16
+ return `${VAULT_ITEM_MARKER} ${JSON.stringify(ask)}\nI need ${what}${where} and there is nothing in your vault for it.${why} Add it to your vault and I will use it without seeing it, or take over my screen and type it yourself.`;
17
+ }
18
+ /** The marker's payload, if a prompt carries one. Clients call this. */
19
+ export function parseVaultItemPrompt(prompt) {
20
+ if (!prompt.startsWith(VAULT_ITEM_MARKER))
21
+ return null;
22
+ const nl = prompt.indexOf("\n");
23
+ const head = nl === -1 ? prompt : prompt.slice(0, nl);
24
+ try {
25
+ const ask = JSON.parse(head.slice(VAULT_ITEM_MARKER.length).trim());
26
+ return { ask, text: nl === -1 ? "" : prompt.slice(nl + 1) };
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /** A client that saved the item answers with this; the tool reads the id out of it. */
33
+ export const SAVED_PREFIX = "vault:";
34
+ export function savedAnswer(itemId) {
35
+ return `${SAVED_PREFIX}${itemId}`;
36
+ }
37
+ /** What the agent's tool file passes to `ctx.ask`. The tool itself must be authored in `agent/tools/` — eve compiles `"use workflow"` from source, so a package cannot ship it. */
38
+ export function vaultItemAsk(input) {
39
+ return {
40
+ prompt: vaultItemPrompt(input),
41
+ display: "select",
42
+ allowFreeform: true,
43
+ options: [
44
+ { id: "manual", label: "I'll type it myself on your screen" },
45
+ { id: "cancel", label: "Cancel", style: "danger" },
46
+ ],
47
+ };
48
+ }
49
+ /** Turn the person's answer into the tool's result. */
50
+ export function interpretVaultAnswer(answer) {
51
+ if (answer.status === "unavailable")
52
+ return { status: "unavailable", note: "No one can answer here (an unattended run). Stop and say what you need." };
53
+ if (answer.status === "dismissed" || answer.optionId === "cancel")
54
+ return { status: "cancelled", note: "The person cancelled. Do not try another way to get these details." };
55
+ if (answer.optionId === "manual")
56
+ return { status: "manual", note: "The person will type it on your screen. Take a screenshot every ~20 seconds until the form is filled or the page changes, then continue; do not touch the fields." };
57
+ const text = (answer.text ?? "").trim();
58
+ if (text.startsWith(SAVED_PREFIX)) {
59
+ const id = text.slice(SAVED_PREFIX.length).trim();
60
+ return { status: "saved", item_id: id, note: `Saved to the vault as ${id}. Call fill_from_vault with this id and the field selectors.` };
61
+ }
62
+ return { status: "cancelled", note: text ? `The person replied: ${text.slice(0, 200)}` : "No usable answer." };
63
+ }
64
+ export const REQUEST_VAULT_ITEM_DESCRIPTION = "Ask the person for a login, card, address or contact you need but could not find in their vault (use list_vault first). The turn pauses until they answer. They can add it to the vault (you get an item id to use with fill_from_vault), take over your screen to type it themselves, or cancel. Never ask for secrets in chat; use this.";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/vault",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "The person's password and card vault, usable by their eve agent on its own computer: the agent sees labels and handles, the control plane holds the secrets, and a fill tool types them into the page so they are never in the transcript.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -15,7 +15,12 @@
15
15
  "import": "./dist/index.js",
16
16
  "default": "./dist/index.js"
17
17
  },
18
- "./package.json": "./package.json"
18
+ "./package.json": "./package.json",
19
+ "./ask": {
20
+ "types": "./dist/request.d.ts",
21
+ "import": "./dist/request.js",
22
+ "default": "./dist/request.js"
23
+ }
19
24
  },
20
25
  "files": [
21
26
  "dist",