@agentick/secrets 0.7.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/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # @agentick/secrets
2
+
3
+ Platform-native secret storage for Agentick agents. Stores credentials in
4
+ the OS keychain on macOS and Linux, with env var fallback everywhere else.
5
+
6
+ ## Install
7
+
8
+ ```sh
9
+ pnpm add @agentick/secrets
10
+ ```
11
+
12
+ ## Quick Start
13
+
14
+ ```typescript
15
+ import { createSecretStore } from "@agentick/secrets";
16
+
17
+ const secrets = await createSecretStore();
18
+
19
+ await secrets.set("telegram.token", "bot123:ABC-xyz");
20
+ const token = await secrets.get("telegram.token");
21
+ ```
22
+
23
+ `createSecretStore()` auto-detects the best backend for the current platform.
24
+
25
+ ## How It Works
26
+
27
+ ```
28
+ createSecretStore()
29
+ |
30
+ v
31
+ Platform detection
32
+ |
33
+ +-- macOS ------> Keychain (security CLI)
34
+ +-- Linux ------> libsecret (secret-tool CLI)
35
+ +-- Fallback ---> Environment variables
36
+ ```
37
+
38
+ All keychain operations use `execFile` with argument arrays — no shell
39
+ interpolation, no injection risk.
40
+
41
+ ## Backends
42
+
43
+ ### Keychain (macOS)
44
+
45
+ Stores secrets in the macOS Keychain via the `security` CLI. Secrets are
46
+ encrypted at rest, protected by the login keychain, and accessible to
47
+ Keychain Access.app.
48
+
49
+ ```typescript
50
+ import { createKeychainStore } from "@agentick/secrets";
51
+
52
+ const secrets = createKeychainStore({ service: "my-agent" });
53
+ ```
54
+
55
+ The `service` parameter scopes secrets (default: `"agentick"`). A manifest
56
+ key tracks all stored keys for `list()`.
57
+
58
+ ### libsecret (Linux)
59
+
60
+ Stores secrets via `secret-tool`, the CLI for GNOME Keyring / KWallet.
61
+ Requires `libsecret` and a running secret service.
62
+
63
+ ```typescript
64
+ import { createLibsecretStore } from "@agentick/secrets";
65
+
66
+ const secrets = createLibsecretStore({ service: "my-agent" });
67
+ ```
68
+
69
+ `list()` uses `secret-tool search` natively — no manifest needed.
70
+
71
+ ### Environment Variables
72
+
73
+ Reads from `process.env`. Dot-path keys are normalized to `UPPER_SNAKE_CASE`.
74
+
75
+ ```typescript
76
+ import { createEnvStore } from "@agentick/secrets";
77
+
78
+ const secrets = createEnvStore({ prefix: "MYAGENT" });
79
+
80
+ // secrets.get("telegram.token") → process.env.MYAGENT_TELEGRAM_TOKEN
81
+ ```
82
+
83
+ Without a prefix, keys map directly: `telegram.token` → `TELEGRAM_TOKEN`.
84
+
85
+ ### Memory
86
+
87
+ In-memory Map. For testing.
88
+
89
+ ```typescript
90
+ import { createMemoryStore } from "@agentick/secrets";
91
+
92
+ const secrets = createMemoryStore({ "api.key": "test-value" });
93
+ ```
94
+
95
+ ## Explicit Backend Selection
96
+
97
+ Override auto-detection when needed.
98
+
99
+ ```typescript
100
+ const secrets = await createSecretStore({ backend: "env", envPrefix: "MYAPP" });
101
+ const secrets = await createSecretStore({ backend: "keychain", service: "my-agent" });
102
+ const secrets = await createSecretStore({ backend: "memory" });
103
+ ```
104
+
105
+ ## Use with Connectors
106
+
107
+ Pass a secret store to connectors instead of hardcoding tokens.
108
+
109
+ ```typescript
110
+ import { createSecretStore } from "@agentick/secrets";
111
+ import { TelegramPlatform } from "@agentick/connector-telegram";
112
+
113
+ const secrets = await createSecretStore();
114
+ const token = await secrets.get("telegram.token");
115
+
116
+ const platform = new TelegramPlatform({ token: token! });
117
+ ```
118
+
119
+ ## SecretStore Interface
120
+
121
+ Defined in `@agentick/shared` so any package can accept it as a dependency.
122
+
123
+ ```typescript
124
+ interface SecretStore {
125
+ get(key: string): Promise<string | null>;
126
+ set(key: string, value: string): Promise<void>;
127
+ delete(key: string): Promise<boolean>;
128
+ has(key: string): Promise<boolean>;
129
+ list(): Promise<string[]>;
130
+ readonly backend: string;
131
+ }
132
+ ```
133
+
134
+ ## Exports
135
+
136
+ ```typescript
137
+ // Factory (auto-detects backend)
138
+ export { createSecretStore } from "./create-secret-store.js";
139
+ export type { CreateSecretStoreOptions, SecretStoreBackend } from "./create-secret-store.js";
140
+
141
+ // Backends
142
+ export { createKeychainStore } from "./keychain-store.js";
143
+ export { createLibsecretStore } from "./libsecret-store.js";
144
+ export { createEnvStore } from "./env-store.js";
145
+ export { createMemoryStore } from "./memory-store.js";
146
+ export type { KeychainStoreOptions } from "./keychain-store.js";
147
+ export type { LibsecretStoreOptions } from "./libsecret-store.js";
148
+ export type { EnvStoreOptions } from "./env-store.js";
149
+
150
+ // Interface (re-exported from @agentick/shared)
151
+ export type { SecretStore } from "@agentick/shared";
152
+ ```
@@ -0,0 +1,9 @@
1
+ import type { SecretStore } from "@agentick/shared";
2
+ export type SecretStoreBackend = "keychain" | "libsecret" | "env" | "memory" | "auto";
3
+ export interface CreateSecretStoreOptions {
4
+ backend?: SecretStoreBackend;
5
+ service?: string;
6
+ envPrefix?: string;
7
+ }
8
+ export declare function createSecretStore(options?: CreateSecretStoreOptions): Promise<SecretStore>;
9
+ //# sourceMappingURL=create-secret-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-secret-store.d.ts","sourceRoot":"","sources":["../src/create-secret-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAMpD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtF,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD,wBAAsB,iBAAiB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBhG"}
@@ -0,0 +1,35 @@
1
+ import { exec } from "./shell.js";
2
+ import { createKeychainStore } from "./keychain-store.js";
3
+ import { createLibsecretStore } from "./libsecret-store.js";
4
+ import { createEnvStore } from "./env-store.js";
5
+ async function isAvailable(cmd) {
6
+ const result = await exec("which", [cmd]);
7
+ return result.exitCode === 0;
8
+ }
9
+ async function detectBackend() {
10
+ if (process.platform === "darwin") {
11
+ return "keychain";
12
+ }
13
+ if (process.platform === "linux" && (await isAvailable("secret-tool"))) {
14
+ return "libsecret";
15
+ }
16
+ return "env";
17
+ }
18
+ export async function createSecretStore(options) {
19
+ const backend = options?.backend === "auto" || !options?.backend ? await detectBackend() : options.backend;
20
+ switch (backend) {
21
+ case "keychain":
22
+ return createKeychainStore({ service: options?.service });
23
+ case "libsecret":
24
+ return createLibsecretStore({ service: options?.service });
25
+ case "env":
26
+ return createEnvStore({ prefix: options?.envPrefix });
27
+ case "memory": {
28
+ const { createMemoryStore } = await import("./memory-store.js");
29
+ return createMemoryStore();
30
+ }
31
+ default:
32
+ throw new Error(`Unknown secret store backend: ${backend}`);
33
+ }
34
+ }
35
+ //# sourceMappingURL=create-secret-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-secret-store.js","sourceRoot":"","sources":["../src/create-secret-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAUhD,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAkC;IACxE,MAAM,OAAO,GACX,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,aAAa,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAE7F,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,mBAAmB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,KAAK,WAAW;YACd,OAAO,oBAAoB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7D,KAAK,KAAK;YACR,OAAO,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACxD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAChE,OAAO,iBAAiB,EAAE,CAAC;QAC7B,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { SecretStore } from "@agentick/shared";
2
+ export interface EnvStoreOptions {
3
+ prefix?: string;
4
+ }
5
+ export declare function createEnvStore(options?: EnvStoreOptions): SecretStore;
6
+ //# sourceMappingURL=env-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-store.d.ts","sourceRoot":"","sources":["../src/env-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAOD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,WAAW,CAmCrE"}
@@ -0,0 +1,36 @@
1
+ function toEnvKey(key, prefix) {
2
+ const normalized = key.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
3
+ return prefix ? `${prefix}_${normalized}` : normalized;
4
+ }
5
+ export function createEnvStore(options) {
6
+ const prefix = options?.prefix?.toUpperCase();
7
+ return {
8
+ backend: "env",
9
+ async get(key) {
10
+ return process.env[toEnvKey(key, prefix)] ?? null;
11
+ },
12
+ async set(key, value) {
13
+ process.env[toEnvKey(key, prefix)] = value;
14
+ },
15
+ async delete(key) {
16
+ const envKey = toEnvKey(key, prefix);
17
+ if (envKey in process.env) {
18
+ delete process.env[envKey];
19
+ return true;
20
+ }
21
+ return false;
22
+ },
23
+ async has(key) {
24
+ return toEnvKey(key, prefix) in process.env;
25
+ },
26
+ async list() {
27
+ const target = prefix ? `${prefix}_` : "";
28
+ if (!target)
29
+ return Object.keys(process.env);
30
+ return Object.keys(process.env)
31
+ .filter((k) => k.startsWith(target))
32
+ .map((k) => k.slice(target.length).toLowerCase().replace(/_/g, "."));
33
+ },
34
+ };
35
+ }
36
+ //# sourceMappingURL=env-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-store.js","sourceRoot":"","sources":["../src/env-store.ts"],"names":[],"mappings":"AAMA,SAAS,QAAQ,CAAC,GAAW,EAAE,MAAe;IAC5C,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACtD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAE9C,OAAO;QACL,OAAO,EAAE,KAAK;QAEd,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC;QACpD,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;YAClB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACrC,IAAI,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC;QAC9C,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM;gBAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;iBAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;iBACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACzE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type { SecretStore } from "@agentick/shared";
2
+ export { createSecretStore, type CreateSecretStoreOptions, type SecretStoreBackend, } from "./create-secret-store.js";
3
+ export { createKeychainStore, type KeychainStoreOptions } from "./keychain-store.js";
4
+ export { createLibsecretStore, type LibsecretStoreOptions } from "./libsecret-store.js";
5
+ export { createEnvStore, type EnvStoreOptions } from "./env-store.js";
6
+ export { createMemoryStore } from "./memory-store.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { createSecretStore, } from "./create-secret-store.js";
2
+ export { createKeychainStore } from "./keychain-store.js";
3
+ export { createLibsecretStore } from "./libsecret-store.js";
4
+ export { createEnvStore } from "./env-store.js";
5
+ export { createMemoryStore } from "./memory-store.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,GAGlB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAA6B,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAA8B,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,cAAc,EAAwB,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { SecretStore } from "@agentick/shared";
2
+ export interface KeychainStoreOptions {
3
+ service?: string;
4
+ }
5
+ export declare function createKeychainStore(options?: KeychainStoreOptions): SecretStore;
6
+ //# sourceMappingURL=keychain-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain-store.d.ts","sourceRoot":"","sources":["../src/keychain-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAMpD,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,WAAW,CAsF/E"}
@@ -0,0 +1,83 @@
1
+ import { exec } from "./shell.js";
2
+ const SERVICE = "agentick";
3
+ const MANIFEST_KEY = "__manifest__";
4
+ export function createKeychainStore(options) {
5
+ const service = options?.service ?? SERVICE;
6
+ async function getManifest() {
7
+ const raw = await rawGet(MANIFEST_KEY);
8
+ if (!raw)
9
+ return [];
10
+ try {
11
+ return JSON.parse(raw);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ async function saveManifest(keys) {
18
+ await rawSet(MANIFEST_KEY, JSON.stringify(keys));
19
+ }
20
+ async function rawGet(key) {
21
+ const result = await exec("security", [
22
+ "find-generic-password",
23
+ "-s",
24
+ service,
25
+ "-a",
26
+ key,
27
+ "-w",
28
+ ]);
29
+ if (result.exitCode !== 0)
30
+ return null;
31
+ return result.stdout;
32
+ }
33
+ async function rawSet(key, value) {
34
+ // Delete first to avoid "already exists" error, then add
35
+ await exec("security", ["delete-generic-password", "-s", service, "-a", key]);
36
+ const result = await exec("security", [
37
+ "add-generic-password",
38
+ "-s",
39
+ service,
40
+ "-a",
41
+ key,
42
+ "-w",
43
+ value,
44
+ ]);
45
+ if (result.exitCode !== 0) {
46
+ throw new Error(`Keychain set failed for "${key}": ${result.stderr}`);
47
+ }
48
+ }
49
+ async function rawDelete(key) {
50
+ const result = await exec("security", ["delete-generic-password", "-s", service, "-a", key]);
51
+ return result.exitCode === 0;
52
+ }
53
+ return {
54
+ backend: "keychain",
55
+ async get(key) {
56
+ return rawGet(key);
57
+ },
58
+ async set(key, value) {
59
+ await rawSet(key, value);
60
+ const manifest = await getManifest();
61
+ if (!manifest.includes(key)) {
62
+ manifest.push(key);
63
+ await saveManifest(manifest);
64
+ }
65
+ },
66
+ async delete(key) {
67
+ const deleted = await rawDelete(key);
68
+ if (deleted) {
69
+ const manifest = await getManifest();
70
+ const updated = manifest.filter((k) => k !== key);
71
+ await saveManifest(updated);
72
+ }
73
+ return deleted;
74
+ },
75
+ async has(key) {
76
+ return (await rawGet(key)) !== null;
77
+ },
78
+ async list() {
79
+ return getManifest();
80
+ },
81
+ };
82
+ }
83
+ //# sourceMappingURL=keychain-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain-store.js","sourceRoot":"","sources":["../src/keychain-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { SecretStore } from "@agentick/shared";
2
+ export interface LibsecretStoreOptions {
3
+ service?: string;
4
+ }
5
+ export declare function createLibsecretStore(options?: LibsecretStoreOptions): SecretStore;
6
+ //# sourceMappingURL=libsecret-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libsecret-store.d.ts","sourceRoot":"","sources":["../src/libsecret-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKpD,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,WAAW,CA4CjF"}
@@ -0,0 +1,41 @@
1
+ import { exec, execWithStdin } from "./shell.js";
2
+ const SERVICE = "agentick";
3
+ export function createLibsecretStore(options) {
4
+ const service = options?.service ?? SERVICE;
5
+ return {
6
+ backend: "libsecret",
7
+ async get(key) {
8
+ const result = await exec("secret-tool", ["lookup", "service", service, "key", key]);
9
+ if (result.exitCode !== 0 || !result.stdout)
10
+ return null;
11
+ return result.stdout;
12
+ },
13
+ async set(key, value) {
14
+ const result = await execWithStdin("secret-tool", ["store", `--label=${service}: ${key}`, "service", service, "key", key], value);
15
+ if (result.exitCode !== 0) {
16
+ throw new Error(`libsecret set failed for "${key}": ${result.stderr}`);
17
+ }
18
+ },
19
+ async delete(key) {
20
+ const result = await exec("secret-tool", ["clear", "service", service, "key", key]);
21
+ return result.exitCode === 0;
22
+ },
23
+ async has(key) {
24
+ const result = await exec("secret-tool", ["lookup", "service", service, "key", key]);
25
+ return result.exitCode === 0 && result.stdout !== "";
26
+ },
27
+ async list() {
28
+ const result = await exec("secret-tool", ["search", "service", service]);
29
+ if (result.exitCode !== 0 || !result.stdout)
30
+ return [];
31
+ const keys = [];
32
+ for (const line of result.stdout.split("\n")) {
33
+ const match = line.match(/^attribute\.key = (.+)$/);
34
+ if (match)
35
+ keys.push(match[1]);
36
+ }
37
+ return keys;
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=libsecret-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libsecret-store.js","sourceRoot":"","sources":["../src/libsecret-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,OAAO,GAAG,UAAU,CAAC;AAM3B,MAAM,UAAU,oBAAoB,CAAC,OAA+B;IAClE,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC;IAE5C,OAAO;QACL,OAAO,EAAE,WAAW;QAEpB,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACrF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACzD,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;YAClB,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,aAAa,EACb,CAAC,OAAO,EAAE,WAAW,OAAO,KAAK,GAAG,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,EACvE,KAAK,CACN,CAAC;YACF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACpF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;YACrF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC;QACvD,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;YACzE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;gBAAE,OAAO,EAAE,CAAC;YACvD,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBACpD,IAAI,KAAK;oBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecretStore } from "@agentick/shared";
2
+ export declare function createMemoryStore(initial?: Record<string, string>): SecretStore;
3
+ //# sourceMappingURL=memory-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../src/memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,WAAW,CA0B/E"}
@@ -0,0 +1,22 @@
1
+ export function createMemoryStore(initial) {
2
+ const secrets = new Map(initial ? Object.entries(initial) : []);
3
+ return {
4
+ backend: "memory",
5
+ async get(key) {
6
+ return secrets.get(key) ?? null;
7
+ },
8
+ async set(key, value) {
9
+ secrets.set(key, value);
10
+ },
11
+ async delete(key) {
12
+ return secrets.delete(key);
13
+ },
14
+ async has(key) {
15
+ return secrets.has(key);
16
+ },
17
+ async list() {
18
+ return [...secrets.keys()];
19
+ },
20
+ };
21
+ }
22
+ //# sourceMappingURL=memory-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../src/memory-store.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,OAAgC;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAiB,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhF,OAAO;QACL,OAAO,EAAE,QAAQ;QAEjB,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAClC,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,IAAI;YACR,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface ExecResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }
6
+ export declare function exec(cmd: string, args: string[]): Promise<ExecResult>;
7
+ export declare function execWithStdin(cmd: string, args: string[], input: string): Promise<ExecResult>;
8
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgBD,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAUrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAY7F"}
package/dist/shell.js ADDED
@@ -0,0 +1,43 @@
1
+ import { execFile as execFileCb } from "node:child_process";
2
+ function extractExitCode(error) {
3
+ if (!error)
4
+ return 0;
5
+ // ENOENT = command not found
6
+ if (error.code === "ENOENT")
7
+ return -1;
8
+ // ExecException: .status holds the exit code on macOS/Linux
9
+ const status = error.status;
10
+ if (typeof status === "number")
11
+ return status;
12
+ // Fallback: .code might be the exit code as a number
13
+ const code = error.code;
14
+ if (typeof code === "number")
15
+ return code;
16
+ // Error exists but no exit code found — assume non-zero
17
+ return 1;
18
+ }
19
+ export function exec(cmd, args) {
20
+ return new Promise((resolve) => {
21
+ execFileCb(cmd, args, { encoding: "utf-8" }, (error, stdout, stderr) => {
22
+ resolve({
23
+ stdout: (stdout ?? "").trim(),
24
+ stderr: (stderr ?? "").trim(),
25
+ exitCode: extractExitCode(error),
26
+ });
27
+ });
28
+ });
29
+ }
30
+ export function execWithStdin(cmd, args, input) {
31
+ return new Promise((resolve) => {
32
+ const child = execFileCb(cmd, args, { encoding: "utf-8" }, (error, stdout, stderr) => {
33
+ resolve({
34
+ stdout: (stdout ?? "").trim(),
35
+ stderr: (stderr ?? "").trim(),
36
+ exitCode: extractExitCode(error),
37
+ });
38
+ });
39
+ child.stdin?.write(input);
40
+ child.stdin?.end();
41
+ });
42
+ }
43
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQ5D,SAAS,eAAe,CAAC,KAAmB;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,6BAA6B;IAC7B,IAAK,KAAa,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,CAAC;IAChD,4DAA4D;IAC5D,MAAM,MAAM,GAAI,KAAa,CAAC,MAAM,CAAC;IACrC,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,qDAAqD;IACrD,MAAM,IAAI,GAAI,KAAa,CAAC,IAAI,CAAC;IACjC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,wDAAwD;IACxD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,IAAc;IAC9C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACrE,OAAO,CAAC;gBACN,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC7B,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC7B,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAc,EAAE,KAAa;IACtE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACnF,OAAO,CAAC;gBACN,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC7B,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC7B,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@agentick/secrets",
3
+ "version": "0.7.0",
4
+ "description": "Platform-native secret storage for Agentick agents",
5
+ "keywords": [
6
+ "agent",
7
+ "ai",
8
+ "credentials",
9
+ "keychain",
10
+ "secrets"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "Ryan Lindgren",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/agenticklabs/agentick.git",
17
+ "directory": "packages/secrets"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "type": "module",
23
+ "main": "src/index.ts",
24
+ "exports": {
25
+ ".": "./src/index.ts"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
+ }
34
+ },
35
+ "main": "./dist/index.js",
36
+ "types": "./dist/index.d.ts"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.build.json",
40
+ "test": "echo \"Tests run from workspace root\"",
41
+ "typecheck": "tsc -p tsconfig.build.json --noEmit",
42
+ "lint": "oxlint src/",
43
+ "format:check": "oxfmt --check src/",
44
+ "clean": "rm -rf dist tsconfig.build.tsbuildinfo",
45
+ "prepublishOnly": "pnpm build",
46
+ "dev": "tsc --watch"
47
+ },
48
+ "dependencies": {
49
+ "@agentick/shared": "workspace:*"
50
+ },
51
+ "devDependencies": {
52
+ "typescript": "^5.8.3"
53
+ }
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export type { SecretStore } from "@agentick/shared";
2
+ export {
3
+ createSecretStore,
4
+ type CreateSecretStoreOptions,
5
+ type SecretStoreBackend,
6
+ } from "./create-secret-store.js";
7
+ export { createKeychainStore, type KeychainStoreOptions } from "./keychain-store.js";
8
+ export { createLibsecretStore, type LibsecretStoreOptions } from "./libsecret-store.js";
9
+ export { createEnvStore, type EnvStoreOptions } from "./env-store.js";
10
+ export { createMemoryStore } from "./memory-store.js";