@emaxe/oa 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -9,6 +9,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ---
11
11
 
12
+ ## [0.3.0] - 2026-09-11
13
+
14
+ ### Added
15
+ - **Personal API Keys**: `oa login` now issues a personal key by default — valid across every team you belong to (with your real role in each), instead of one agent key per team. Use `oa login --agent` for the old behavior: a key locked to one team, for CI and narrowly-scoped use cases.
16
+ - **`oa orgs`**: Lists the teams your key can act in, marking the one currently selected for this project.
17
+ - **`oa use <team>`**: Sets the default team for the current project, saved to a `.oa.json` file next to it (no secrets — safe to commit). Pass `--global` to set it for the whole machine instead.
18
+ - **`--org <team>` flag**: Added to `oa list` and `oa push` to override the resolved default team for a single invocation.
19
+ - **Project-scoped config resolution**: `.oa.json` is found by walking up from the current directory, the same way `.git`/`.eslintrc` are — so the right team is picked up automatically no matter which subdirectory a command runs from.
20
+
21
+ ### Changed
22
+ - Structured handling of the new `org_required` error: when a personal key belongs to more than one team and none is selected, the CLI prints the candidate list and points at `oa use`/`--org` instead of a raw error.
23
+ - Credentials file permissions (`600`) are now re-applied on every login, not just when the file is first created.
24
+
25
+ ---
26
+
12
27
  ## [0.2.0] - 2026-09-11
13
28
 
14
29
  ### Added
package/CHANGELOG.ru.md CHANGED
@@ -9,6 +9,21 @@
9
9
 
10
10
  ---
11
11
 
12
+ ## [0.3.0] - 2026-09-11
13
+
14
+ ### Добавлено
15
+ - **Личные API-ключи**: `oa login` теперь по умолчанию выпускает личный ключ — действующий во всех ваших командах (с вашей реальной ролью в каждой) вместо отдельного ключа агента на команду. Прежнее поведение (ключ, запертый в одной команде — для CI и узких прав) доступно через `oa login --agent`.
16
+ - **`oa orgs`**: Список команд, доступных ключу, с отметкой текущей выбранной для этого проекта.
17
+ - **`oa use <team>`**: Устанавливает команду по умолчанию для текущего проекта — сохраняется в файл `.oa.json` рядом с ним (без секретов, можно коммитить). Флаг `--global` задаёт значение для всего компьютера.
18
+ - **Флаг `--org <team>`**: Добавлен в `oa list` и `oa push` для разового переопределения выбранной команды.
19
+ - **Разрешение конфигурации по проекту**: `.oa.json` ищется подъёмом вверх по дереву каталогов от текущей директории — так же, как `.git`/`.eslintrc` — поэтому нужная команда подхватывается автоматически из любой вложенной папки.
20
+
21
+ ### Изменено
22
+ - Структурированная обработка новой ошибки `org_required`: если у личного ключа несколько команд и ни одна не выбрана, CLI печатает список кандидатов и подсказывает `oa use`/`--org` вместо сырой ошибки.
23
+ - Права на файл с учётными данными (`600`) теперь применяются при каждом логине, а не только при первом создании файла.
24
+
25
+ ---
26
+
12
27
  ## [0.2.0] - 2026-09-11
13
28
 
14
29
  ### Добавлено
package/README.md CHANGED
@@ -42,7 +42,7 @@ Connect to your Open Artifacts server using the interactive OAuth Device Flow:
42
42
  oa login --server https://artifacts.your-company.com
43
43
  ```
44
44
 
45
- The CLI outputs a short code (e.g. `ABCD-1234`) and an activation link. Open the link in your browser, select your organization, and approve access. Credentials are saved locally to `~/.config/open-artifacts/credentials.json` (`600` permissions).
45
+ The CLI outputs a short code (e.g. `ABCD-1234`) and an activation link. Open the link in your browser and approve access. This issues a **personal key** by default — it's valid across every team you belong to, not locked to one. Credentials are saved locally to `~/.config/open-artifacts/credentials.json` (`600` permissions).
46
46
 
47
47
  Verify your session at any time:
48
48
 
@@ -50,7 +50,18 @@ Verify your session at any time:
50
50
  oa whoami
51
51
  ```
52
52
 
53
- ### 2. Publish Content
53
+ ### 2. Pick a team
54
+
55
+ If you belong to more than one team, tell the CLI which one to use for this project:
56
+
57
+ ```bash
58
+ oa orgs # list your teams, with a * next to the current default
59
+ oa use <team> # set the default for this project (writes a secret-free .oa.json you can commit)
60
+ ```
61
+
62
+ With exactly one team, this step is optional — it's used automatically. Override it for a single command with `--org <team>` on `oa list` / `oa push`, without changing the saved default.
63
+
64
+ ### 3. Publish Content
54
65
 
55
66
  ```bash
56
67
  # Publish an HTML file and get a public shareable URL:
@@ -76,12 +87,27 @@ Authorizes the CLI with an Open Artifacts server using the OAuth device flow.
76
87
  ```bash
77
88
  oa login [options]
78
89
  --server <url> Open Artifacts server URL (default: "http://localhost:3000")
79
- --name <name> Agent or client name to register
90
+ --name <name> Name to register this device/agent as
80
91
  --scopes <scopes> Comma-separated list of scopes (default: "artifacts:read,artifacts:write,shares:write")
92
+ --agent Issue an agent key locked to one team, instead of a personal key spanning all your teams
81
93
  ```
82
94
 
83
95
  ### `oa whoami`
84
- Displays current credentials, server endpoint, organization ID, and token expiration.
96
+ Displays current credentials, server endpoint, key type, effective team, and token expiration.
97
+
98
+ ### `oa orgs`
99
+ Lists the teams your key can act in, marking the one currently selected for this project.
100
+
101
+ ```bash
102
+ oa orgs [--json]
103
+ ```
104
+
105
+ ### `oa use <team>`
106
+ Sets the default team (by id or slug) for the current project, or for the whole machine.
107
+
108
+ ```bash
109
+ oa use <team> [--global]
110
+ ```
85
111
 
86
112
  ### `oa push <file>`
87
113
  Creates a new artifact or updates an existing one from a local file.
@@ -95,14 +121,15 @@ oa push <file> [options]
95
121
  --password <pass> Protect the share link with a password (implies --share)
96
122
  --expires <ttl> Share expiration: 1h, 1d, 7d, 30d (implies --share)
97
123
  --message <msg> Version commit message
124
+ --org <team> Team id or slug to publish into (overrides the project/machine default)
98
125
  --json Output result as JSON
99
126
  ```
100
127
 
101
128
  ### `oa list`
102
- Lists all artifacts in your active organization.
129
+ Lists all artifacts in your active team.
103
130
 
104
131
  ```bash
105
- oa list [--json]
132
+ oa list [--org <team>] [--json]
106
133
  ```
107
134
 
108
135
  ### `oa get <artifact-id>`
@@ -147,7 +174,7 @@ export OA_SERVER="https://artifacts.your-company.com"
147
174
  export OA_TOKEN="oa_live_xxxxxxxxxxxxxxxxxxxxxxxx"
148
175
  ```
149
176
 
150
- Generate agent API tokens directly in the Open Artifacts web dashboard under **Team > Agents**.
177
+ For CI, an agent key (`oa login --agent`, or generated in the web dashboard under **Team > Agents**) is usually the right choice — it's locked to one team, which keeps the blast radius of a leaked CI secret small. A personal key issued from **Settings > Личные API-ключи** also works via `OA_TOKEN`, but it spans every team you belong to.
151
178
 
152
179
  ---
153
180
 
package/README.ru.md CHANGED
@@ -42,7 +42,7 @@ npx @emaxe/oa --help
42
42
  oa login --server https://artifacts.your-company.com
43
43
  ```
44
44
 
45
- Утилита сгенерирует короткий код подтверждения (например, `ABCD-1234`) и ссылку на страницу активации. Перейдите по ссылке, выберите организацию и разрешите доступ. Токен сохранится локально в `~/.config/open-artifacts/credentials.json` с правами `600`.
45
+ Утилита сгенерирует короткий код подтверждения (например, `ABCD-1234`) и ссылку на страницу активации. Перейдите по ссылке и разрешите доступ. По умолчанию выпускается **личный ключ** — он действует во всех ваших командах, а не запертый в одной. Токен сохранится локально в `~/.config/open-artifacts/credentials.json` с правами `600`.
46
46
 
47
47
  Проверить статус сессии в любой момент:
48
48
 
@@ -50,7 +50,18 @@ oa login --server https://artifacts.your-company.com
50
50
  oa whoami
51
51
  ```
52
52
 
53
- ### 2. Публикация файлов
53
+ ### 2. Выбор команды
54
+
55
+ Если вы состоите в нескольких командах, укажите CLI, какую использовать для этого проекта:
56
+
57
+ ```bash
58
+ oa orgs # список ваших команд с отметкой * у текущей по умолчанию
59
+ oa use <team> # задать команду по умолчанию для проекта (пишет .oa.json без секретов, можно коммитить)
60
+ ```
61
+
62
+ Если команда одна — этот шаг не нужен, она подставится автоматически. Переопределить для одного вызова можно флагом `--org <team>` у `oa list`/`oa push`, не меняя сохранённое значение по умолчанию.
63
+
64
+ ### 3. Публикация файлов
54
65
 
55
66
  ```bash
56
67
  # Опубликовать HTML-страницу и получить публичную ссылку:
@@ -76,12 +87,27 @@ oa push diagram.svg --title "Схема базы данных" --share
76
87
  ```bash
77
88
  oa login [options]
78
89
  --server <url> URL сервера Open Artifacts (по умолчанию: "http://localhost:3000")
79
- --name <name> Имя регистрируемого агента
90
+ --name <name> Имя регистрируемого устройства/агента
80
91
  --scopes <scopes> Список запрашиваемых прав через запятую (по умолчанию: "artifacts:read,artifacts:write,shares:write")
92
+ --agent Выпустить ключ агента, запертый в одной команде, вместо личного ключа на все ваши команды
81
93
  ```
82
94
 
83
95
  ### `oa whoami`
84
- Показывает текущие учетные данные, адрес сервера, идентификатор организации и статус токена.
96
+ Показывает текущие учётные данные, адрес сервера, тип ключа, выбранную команду и статус токена.
97
+
98
+ ### `oa orgs`
99
+ Список команд, доступных ключу, с отметкой текущей выбранной для этого проекта.
100
+
101
+ ```bash
102
+ oa orgs [--json]
103
+ ```
104
+
105
+ ### `oa use <team>`
106
+ Задаёт команду по умолчанию (по id или slug) для текущего проекта или для всего компьютера.
107
+
108
+ ```bash
109
+ oa use <team> [--global]
110
+ ```
85
111
 
86
112
  ### `oa push <file>`
87
113
  Создает новый артефакт или обновляет существующий из локального файла.
@@ -95,14 +121,15 @@ oa push <file> [options]
95
121
  --password <pass> Защитить ссылку паролем (включает --share)
96
122
  --expires <ttl> Срок действия ссылки: 1h, 1d, 7d, 30d (включает --share)
97
123
  --message <msg> Сообщение версии
124
+ --org <team> Команда для публикации (переопределяет значение по умолчанию проекта/машины)
98
125
  --json Вывод результата в формате JSON
99
126
  ```
100
127
 
101
128
  ### `oa list`
102
- Выводит список всех артефактов в текущей организации.
129
+ Выводит список всех артефактов в текущей команде.
103
130
 
104
131
  ```bash
105
- oa list [--json]
132
+ oa list [--org <team>] [--json]
106
133
  ```
107
134
 
108
135
  ### `oa get <artifact-id>`
@@ -147,7 +174,7 @@ export OA_SERVER="https://artifacts.your-company.com"
147
174
  export OA_TOKEN="oa_live_xxxxxxxxxxxxxxxxxxxxxxxx"
148
175
  ```
149
176
 
150
- Токены агентов создаются в панели управления Open Artifacts в разделе **Команда > Агенты**.
177
+ Для CI обычно правильный выбор — ключ агента (`oa login --agent`, либо выпущенный в панели управления в разделе **Команда > Агенты**): он заперт в одной команде, что ограничивает ущерб от утечки CI-секрета. Личный ключ из **Настройки > Личные API-ключи** тоже подходит для `OA_TOKEN`, но действует во всех ваших командах.
151
178
 
152
179
  ---
153
180
 
@@ -0,0 +1,60 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { resolveOrg } from "../org.js";
6
+ let dir;
7
+ afterEach(() => {
8
+ if (dir)
9
+ rmSync(dir, { recursive: true, force: true });
10
+ dir = undefined;
11
+ });
12
+ function makeTmpDir() {
13
+ dir = mkdtempSync(join(tmpdir(), "oa-org-resolution-"));
14
+ return dir;
15
+ }
16
+ const userCreds = { server: "https://oa.example.com", token: "oa_live_x", expiresAt: null, kind: "user", userId: "u1" };
17
+ const legacyAgentCreds = { server: "https://oa.example.com", token: "oa_live_x", expiresAt: null, agentId: "a1", orgId: "org-legacy" };
18
+ describe("resolveOrg priority", () => {
19
+ it("--org flag wins over everything else", () => {
20
+ const root = makeTmpDir();
21
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-project" }));
22
+ const res = resolveOrg({ flag: "org-flag", cwd: root, env: { OA_ORG: "org-env" }, creds: userCreds });
23
+ expect(res).toEqual({ orgId: "org-flag", source: "flag" });
24
+ });
25
+ it("OA_ORG env wins over the project config", () => {
26
+ const root = makeTmpDir();
27
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-project" }));
28
+ const res = resolveOrg({ cwd: root, env: { OA_ORG: "org-env" }, creds: userCreds });
29
+ expect(res).toEqual({ orgId: "org-env", source: "env" });
30
+ });
31
+ it("falls back to the project's .oa.json when no flag or env is given", () => {
32
+ const root = makeTmpDir();
33
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-project", server: "https://oa.example.com" }));
34
+ const res = resolveOrg({ cwd: root, env: {}, creds: userCreds });
35
+ expect(res).toEqual({ orgId: "org-project", source: "project", configPath: join(root, ".oa.json") });
36
+ });
37
+ it("ignores a project config written for a different server", () => {
38
+ const root = makeTmpDir();
39
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-project", server: "https://other.example.com" }));
40
+ const res = resolveOrg({ cwd: root, env: {}, creds: userCreds });
41
+ expect(res).toEqual({ source: "none" });
42
+ });
43
+ it("falls back to a legacy agent credentials file's locked org when nothing else resolves", () => {
44
+ const root = makeTmpDir();
45
+ const res = resolveOrg({ cwd: root, env: {}, creds: legacyAgentCreds });
46
+ expect(res).toEqual({ orgId: "org-legacy", source: "credentials" });
47
+ });
48
+ it("never falls back to credentials.orgId for a personal (kind: user) key", () => {
49
+ const root = makeTmpDir();
50
+ const personalWithOrg = { ...userCreds, orgId: "should-not-be-used" };
51
+ const res = resolveOrg({ cwd: root, env: {}, creds: personalWithOrg });
52
+ expect(res).toEqual({ source: "none" });
53
+ });
54
+ it("resolves to 'none' with no flag, env, project config, or usable credentials fallback", () => {
55
+ const root = makeTmpDir();
56
+ const res = resolveOrg({ cwd: root, env: {}, creds: userCreds });
57
+ expect(res).toEqual({ source: "none" });
58
+ });
59
+ });
60
+ //# sourceMappingURL=org-resolution.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-resolution.test.js","sourceRoot":"","sources":["../../src/__tests__/org-resolution.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { findProjectConfig, projectConfigTarget, writeProjectConfig } from "../project-config.js";
6
+ let dir;
7
+ afterEach(() => {
8
+ if (dir)
9
+ rmSync(dir, { recursive: true, force: true });
10
+ dir = undefined;
11
+ });
12
+ function makeTmpDir() {
13
+ dir = mkdtempSync(join(tmpdir(), "oa-project-config-"));
14
+ return dir;
15
+ }
16
+ describe("findProjectConfig", () => {
17
+ it("returns null when no .oa.json exists anywhere up to the filesystem root", () => {
18
+ const root = makeTmpDir();
19
+ const nested = join(root, "a", "b");
20
+ mkdirSync(nested, { recursive: true });
21
+ expect(findProjectConfig(nested)).toBeNull();
22
+ });
23
+ it("finds .oa.json in the exact cwd", () => {
24
+ const root = makeTmpDir();
25
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-1" }));
26
+ const found = findProjectConfig(root);
27
+ expect(found?.config.orgId).toBe("org-1");
28
+ });
29
+ it("walks up from a nested subdirectory to find .oa.json in an ancestor", () => {
30
+ const root = makeTmpDir();
31
+ const nested = join(root, "a", "b", "c");
32
+ mkdirSync(nested, { recursive: true });
33
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-root" }));
34
+ const found = findProjectConfig(nested);
35
+ expect(found?.config.orgId).toBe("org-root");
36
+ expect(found?.path).toBe(join(root, ".oa.json"));
37
+ });
38
+ it("prefers the nearest .oa.json over one further up the tree", () => {
39
+ const root = makeTmpDir();
40
+ const nested = join(root, "a", "b");
41
+ mkdirSync(nested, { recursive: true });
42
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-root" }));
43
+ writeFileSync(join(nested, ".oa.json"), JSON.stringify({ orgId: "org-nested" }));
44
+ expect(findProjectConfig(nested)?.config.orgId).toBe("org-nested");
45
+ });
46
+ it("warns and returns null instead of throwing on invalid JSON", () => {
47
+ const root = makeTmpDir();
48
+ writeFileSync(join(root, ".oa.json"), "{ not valid json");
49
+ expect(findProjectConfig(root)).toBeNull();
50
+ });
51
+ });
52
+ describe("projectConfigTarget", () => {
53
+ it("returns the path of an existing .oa.json when one is found", () => {
54
+ const root = makeTmpDir();
55
+ writeFileSync(join(root, ".oa.json"), JSON.stringify({ orgId: "org-1" }));
56
+ expect(projectConfigTarget(root)).toBe(join(root, ".oa.json"));
57
+ });
58
+ it("targets the git root when no .oa.json exists yet", () => {
59
+ const root = makeTmpDir();
60
+ mkdirSync(join(root, ".git"));
61
+ const nested = join(root, "src", "lib");
62
+ mkdirSync(nested, { recursive: true });
63
+ expect(projectConfigTarget(nested)).toBe(join(root, ".oa.json"));
64
+ });
65
+ it("falls back to cwd when neither .oa.json nor a .git root is found", () => {
66
+ const root = makeTmpDir();
67
+ const nested = join(root, "a");
68
+ mkdirSync(nested, { recursive: true });
69
+ expect(projectConfigTarget(nested)).toBe(join(nested, ".oa.json"));
70
+ });
71
+ });
72
+ describe("writeProjectConfig", () => {
73
+ it("creates a new file with the given patch", () => {
74
+ const root = makeTmpDir();
75
+ const path = join(root, ".oa.json");
76
+ writeProjectConfig(path, { orgId: "org-1", orgSlug: "acme" });
77
+ expect(findProjectConfig(root)?.config).toEqual({ orgId: "org-1", orgSlug: "acme" });
78
+ });
79
+ it("merges into an existing file rather than replacing it", () => {
80
+ const root = makeTmpDir();
81
+ const path = join(root, ".oa.json");
82
+ writeFileSync(path, JSON.stringify({ server: "https://oa.example.com" }));
83
+ writeProjectConfig(path, { orgId: "org-1" });
84
+ expect(findProjectConfig(root)?.config).toEqual({ server: "https://oa.example.com", orgId: "org-1" });
85
+ });
86
+ });
87
+ //# sourceMappingURL=project-config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-config.test.js","sourceRoot":"","sources":["../../src/__tests__/project-config.test.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -1,10 +1,14 @@
1
1
  export class CliApiError extends Error {
2
2
  code;
3
3
  status;
4
- constructor(code, message, status) {
4
+ body;
5
+ constructor(code, message, status,
6
+ /** The parsed error body, e.g. `{ error: { code, message, orgs } }` for `org_required`. */
7
+ body) {
5
8
  super(message);
6
9
  this.code = code;
7
10
  this.status = status;
11
+ this.body = body;
8
12
  }
9
13
  }
10
14
  export function makeClient(creds) {
@@ -20,7 +24,7 @@ export function makeClient(creds) {
20
24
  });
21
25
  const body = (await res.json().catch(() => ({})));
22
26
  if (!res.ok) {
23
- throw new CliApiError(body?.error?.code ?? "unknown_error", body?.error?.message ?? res.statusText, res.status);
27
+ throw new CliApiError(body?.error?.code ?? "unknown_error", body?.error?.message ?? res.statusText, res.status, body);
24
28
  }
25
29
  return body;
26
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAY,SAAQ,KAAK;IACjB;IAAsC;IAAzD,YAAmB,IAAY,EAAE,OAAe,EAAS,MAAc;QACrE,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAQ;QAA0B,WAAM,GAAN,MAAM,CAAQ;IAEvE,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC;IAEzD,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,UAAuB,EAAE;QAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;YACxC,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;gBACtC,GAAG,OAAO,CAAC,OAAO;aACnB;SACF,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAoD,CAAC;QACrG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAClH,CAAC;QACD,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,EAAE,CAAI,IAAY,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,CAAC;QAC1C,IAAI,EAAE,CAAI,IAAY,EAAE,IAAc,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAC9H,KAAK,EAAE,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC,EAAE,EAAE,CAC3E,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;QAC5E,MAAM,EAAE,CAAI,IAAY,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAE3B;IAEA;IAEA;IALT,YACS,IAAY,EACnB,OAAe,EACR,MAAc;IACrB,2FAA2F;IACpF,IAA0E;QAEjF,KAAK,CAAC,OAAO,CAAC,CAAC;QANR,SAAI,GAAJ,IAAI,CAAQ;QAEZ,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAsE;IAGnF,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC;IAEzD,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,UAAuB,EAAE;QAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;YACxC,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;gBACtC,GAAG,OAAO,CAAC,OAAO;aACnB;SACF,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAwE,CAAC;QACzH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACxH,CAAC;QACD,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,EAAE,CAAI,IAAY,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,CAAC;QAC1C,IAAI,EAAE,CAAI,IAAY,EAAE,IAAc,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QAC9H,KAAK,EAAE,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC,EAAE,EAAE,CAC3E,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;QAC5E,MAAM,EAAE,CAAI,IAAY,EAAE,EAAE,CAAC,OAAO,CAAI,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC"}
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { extname, basename } from "node:path";
3
3
  import { requireCredentials } from "../config.js";
4
4
  import { makeClient, CliApiError } from "../client.js";
5
+ import { resolveOrg } from "../org.js";
5
6
  export function inferKind(filePath) {
6
7
  const ext = extname(filePath).toLowerCase();
7
8
  if (ext === ".md" || ext === ".markdown")
@@ -19,8 +20,9 @@ function die(message) {
19
20
  export async function listCommand(opts) {
20
21
  const creds = requireCredentials();
21
22
  const client = makeClient(creds);
23
+ const org = resolveOrg({ flag: opts.org, creds });
22
24
  try {
23
- const data = await client.get(`/artifacts?orgId=${creds.orgId}`);
25
+ const data = await client.get(`/artifacts${org.orgId ? `?orgId=${org.orgId}` : ""}`);
24
26
  if (opts.json) {
25
27
  console.log(JSON.stringify(data.artifacts, null, 2));
26
28
  return;
@@ -47,7 +49,10 @@ export async function pushCommand(filePath, opts) {
47
49
  await client.patch(`/artifacts/${artifactId}`, { content, message: opts.message });
48
50
  }
49
51
  else {
50
- const res = await client.post(`/artifacts?orgId=${creds.orgId}`, {
52
+ // Updating an existing artifact never needs an org (the id alone identifies it) — only
53
+ // resolve one when we're about to create.
54
+ const org = resolveOrg({ flag: opts.org, creds });
55
+ const res = await client.post(`/artifacts${org.orgId ? `?orgId=${org.orgId}` : ""}`, {
51
56
  title,
52
57
  kind,
53
58
  content,
@@ -104,6 +109,9 @@ export async function rmCommand(id) {
104
109
  handleError(err);
105
110
  }
106
111
  }
112
+ export function formatOrgChoices(orgs) {
113
+ return orgs.map((o) => ` ${o.slug.padEnd(24)} ${o.role.padEnd(7)} ${o.name}`).join("\n");
114
+ }
107
115
  export function handleError(err) {
108
116
  if (err instanceof CliApiError) {
109
117
  if (err.code === "key_expired") {
@@ -115,6 +123,10 @@ export function handleError(err) {
115
123
  if (err.code === "version_conflict") {
116
124
  die("Someone else changed this artifact since you last read it (409). Fetch the latest with `oa get` and retry.");
117
125
  }
126
+ if (err.code === "org_required") {
127
+ const orgs = err.body?.error?.orgs ?? [];
128
+ die(`Not sure which team to publish to — you belong to several:\n${formatOrgChoices(orgs)}\n\nRun \`oa use <slug>\` to set a default for this project, or pass --org <slug>.`);
129
+ }
118
130
  die(`Error (${err.code}): ${err.message}`);
119
131
  }
120
132
  throw err;
@@ -1 +1 @@
1
- {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/commands/artifacts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/commands/artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAkB,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAUvC,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IAC5D,IAAI,GAAG,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IAC3D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,GAAG,CAAC,OAAe;IAC1B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAsC;IACtE,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAmC,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,IAA8I;IAE9I,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAEjC,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC;QACzB,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,uFAAuF;YACvF,0CAA0C;YAC1C,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAA+B,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE;gBACjH,KAAK;gBACL,IAAI;gBACJ,OAAO;gBACP,UAAU,EAAE,SAAS;aACtB,CAAC,CAAC;YACH,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,MAAM,GAA4B,EAAE,UAAU,EAAE,CAAC;QAEvD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAkB,cAAc,UAAU,SAAS,EAAE;gBACrF,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;gBAC3C,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC,CAAC;YACH,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;QACjC,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;YACvC,IAAI,MAAM,CAAC,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAAU,EAAE,IAAyB;IACpE,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAsB,cAAc,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAU;IACxC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAiB;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAC/B,GAAG,CAAC,iDAAiD,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAClC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACpC,GAAG,CAAC,4GAA4G,CAAC,CAAC;QACpH,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;YACzC,GAAG,CAAC,+DAA+D,gBAAgB,CAAC,IAAI,CAAC,oFAAoF,CAAC,CAAC;QACjL,CAAC;QACD,GAAG,CAAC,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,GAAG,CAAC;AACZ,CAAC"}
@@ -5,11 +5,14 @@ function sleep(ms) {
5
5
  }
6
6
  export async function login(opts) {
7
7
  const server = opts.server.replace(/\/$/, "");
8
- const agentName = opts.name ?? `cli-${hostname()}`;
8
+ // Personal (spans every team the approver belongs to) is the default — `--agent` is for CI and
9
+ // other narrowly-scoped, single-team use cases.
10
+ const grantKind = opts.agent ? "agent" : "user";
11
+ const agentName = opts.name ?? (grantKind === "agent" ? `cli-${hostname()}` : hostname());
9
12
  const codeRes = await fetch(`${server}/api/v1/oauth/device/code`, {
10
13
  method: "POST",
11
14
  headers: { "Content-Type": "application/json" },
12
- body: JSON.stringify({ agentName, scopes: opts.scopes }),
15
+ body: JSON.stringify({ agentName, scopes: opts.scopes, grantKind }),
13
16
  });
14
17
  if (!codeRes.ok) {
15
18
  console.error(`Failed to start device authorization: ${codeRes.status} ${await codeRes.text()}`);
@@ -18,7 +21,7 @@ export async function login(opts) {
18
21
  const device = (await codeRes.json());
19
22
  console.log(`\nTo authorize this device, open:\n\n ${device.verification_uri_complete}\n`);
20
23
  console.log(`If prompted, enter code: ${device.user_code}\n`);
21
- console.log("Waiting for approval...");
24
+ console.log(grantKind === "user" ? "Requesting personal access to all your teams. Waiting for approval..." : "Waiting for approval...");
22
25
  const deadline = Date.now() + device.expires_in * 1000;
23
26
  let interval = device.interval * 1000;
24
27
  while (Date.now() < deadline) {
@@ -30,8 +33,15 @@ export async function login(opts) {
30
33
  });
31
34
  const body = (await tokenRes.json());
32
35
  if ("api_key" in body) {
33
- saveCredentials({ server, token: body.api_key, agentId: body.agent_id, orgId: body.org_id, expiresAt: body.expires_at });
34
- console.log(`\nLogged in. Credentials saved to ~/.config/open-artifacts/credentials.json`);
36
+ if (body.grant_kind === "user") {
37
+ saveCredentials({ server, token: body.api_key, expiresAt: body.expires_at, kind: "user", userId: body.user_id });
38
+ console.log("\nLogged in with a personal key, valid across every team you belong to.");
39
+ console.log("Run `oa orgs` to see them, or `oa use <team>` to pick a default for this project.");
40
+ }
41
+ else {
42
+ saveCredentials({ server, token: body.api_key, expiresAt: body.expires_at, kind: "agent", agentId: body.agent_id, orgId: body.org_id });
43
+ console.log(`\nLogged in. Credentials saved to ~/.config/open-artifacts/credentials.json`);
44
+ }
35
45
  return;
36
46
  }
37
47
  if (body.error === "slow_down") {
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { requireCredentials, saveCredentials } from "../config.js";
2
+ import { makeClient } from "../client.js";
3
+ import { resolveOrg } from "../org.js";
4
+ import { projectConfigTarget, writeProjectConfig } from "../project-config.js";
5
+ import { handleError, formatOrgChoices } from "./artifacts.js";
6
+ export async function orgsCommand(opts) {
7
+ const creds = requireCredentials();
8
+ const client = makeClient(creds);
9
+ try {
10
+ const data = await client.get("/me/orgs");
11
+ if (opts.json) {
12
+ console.log(JSON.stringify(data.orgs, null, 2));
13
+ return;
14
+ }
15
+ const current = resolveOrg({ creds });
16
+ if (data.orgs.length === 0) {
17
+ console.log("No teams found.");
18
+ return;
19
+ }
20
+ console.log(data.orgs
21
+ .map((o) => `${o.orgId === current.orgId ? "* " : " "}${o.slug.padEnd(24)} ${o.role.padEnd(7)} ${o.name}`)
22
+ .join("\n"));
23
+ console.log(current.orgId ? `\nCurrent: ${current.orgId} (from ${current.source})` : "\nNo default team selected for this project — run `oa use <slug>`.");
24
+ }
25
+ catch (err) {
26
+ handleError(err);
27
+ }
28
+ }
29
+ export async function useCommand(idOrSlug, opts) {
30
+ const creds = requireCredentials();
31
+ const client = makeClient(creds);
32
+ try {
33
+ const data = await client.get("/me/orgs");
34
+ const match = data.orgs.find((o) => o.orgId === idOrSlug || o.slug === idOrSlug);
35
+ if (!match) {
36
+ console.error(`No team matching "${idOrSlug}". Run \`oa orgs\` to see what you belong to:\n${formatOrgChoices(data.orgs)}`);
37
+ process.exit(1);
38
+ }
39
+ if (opts.global) {
40
+ saveCredentials({ ...creds, orgId: match.orgId });
41
+ console.log(`Default team for this machine set to ${match.name} (${match.slug}).`);
42
+ return;
43
+ }
44
+ const target = projectConfigTarget(process.cwd());
45
+ writeProjectConfig(target, { orgId: match.orgId, orgSlug: match.slug, server: creds.server });
46
+ console.log(`Default team for this project set to ${match.name} (${match.slug}) — saved to ${target}`);
47
+ }
48
+ catch (err) {
49
+ handleError(err);
50
+ }
51
+ }
52
+ //# sourceMappingURL=orgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgs.js","sourceRoot":"","sources":["../../src/commands/orgs.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { requireCredentials } from "../config.js";
2
2
  import { makeClient } from "../client.js";
3
+ import { resolveOrg } from "../org.js";
3
4
  import { handleError } from "./artifacts.js";
4
5
  export async function shareCommand(id, opts) {
5
6
  const creds = requireCredentials();
@@ -31,12 +32,16 @@ export async function unshareCommand(shareId) {
31
32
  export async function whoamiCommand() {
32
33
  const creds = requireCredentials();
33
34
  const client = makeClient(creds);
35
+ const kind = creds.kind ?? "agent"; // pre-0.3.0 credentials files never recorded kind — always an agent grant
36
+ const org = resolveOrg({ creds });
34
37
  console.log(`Server: ${creds.server}`);
35
- console.log(`Org: ${creds.orgId}`);
36
- console.log(`Agent: ${creds.agentId}`);
38
+ console.log(`Auth: ${kind === "user" ? "personal key (all your teams)" : "agent key"}`);
39
+ if (kind === "agent" && creds.agentId)
40
+ console.log(`Agent: ${creds.agentId}`);
37
41
  console.log(`Expires: ${creds.expiresAt ?? "never"}`);
42
+ console.log(`Team: ${org.orgId ? `${org.orgId} (from ${org.source})` : "not selected — run `oa orgs` / `oa use <team>`"}`);
38
43
  try {
39
- await client.get(`/artifacts?orgId=${creds.orgId}`);
44
+ await client.get(`/artifacts${org.orgId ? `?orgId=${org.orgId}` : ""}`);
40
45
  console.log("Token is valid.");
41
46
  }
42
47
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAU,EAAE,IAA+D;IAC5G,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAiC,cAAc,EAAE,SAAS,EAAE;YACvF,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;YAC3C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;SAC3D,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  const CONFIG_DIR = join(homedir(), ".config", "open-artifacts");
@@ -7,15 +7,18 @@ export function loadCredentials() {
7
7
  const envToken = process.env.OA_TOKEN;
8
8
  const envServer = process.env.OA_SERVER;
9
9
  if (envToken) {
10
- return { server: envServer ?? "http://localhost:3000", token: envToken, agentId: "", orgId: "", expiresAt: null };
10
+ return { server: envServer ?? "http://localhost:3000", token: envToken, expiresAt: null };
11
11
  }
12
12
  if (!existsSync(CREDENTIALS_PATH))
13
13
  return null;
14
14
  return JSON.parse(readFileSync(CREDENTIALS_PATH, "utf8"));
15
15
  }
16
16
  export function saveCredentials(creds) {
17
- mkdirSync(CONFIG_DIR, { recursive: true });
17
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
18
18
  writeFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), { mode: 0o600 });
19
+ // `mode` above is only honored when the file is newly created — chmod explicitly so an
20
+ // overwrite of a pre-existing (possibly more permissive) file still ends up locked down.
21
+ chmodSync(CREDENTIALS_PATH, 0o600);
19
22
  }
20
23
  export function requireCredentials() {
21
24
  const creds = loadCredentials();
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAE9D,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,SAAS,IAAI,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAcjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAE9D,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,SAAS,IAAI,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC5F,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjF,uFAAuF;IACvF,yFAAyF;IACzF,SAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACzE,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/dist/index.js CHANGED
@@ -4,14 +4,16 @@ import { isValidScope, API_KEY_SCOPES } from "./scopes.js";
4
4
  import { login } from "./commands/login.js";
5
5
  import { listCommand, pushCommand, getCommand, rmCommand } from "./commands/artifacts.js";
6
6
  import { shareCommand, unshareCommand, whoamiCommand } from "./commands/share.js";
7
+ import { orgsCommand, useCommand } from "./commands/orgs.js";
7
8
  const program = new Command();
8
- program.name("oa").description("CLI for Open Artifacts — self-hosted artifact hosting for AI agents").version("0.2.0");
9
+ program.name("oa").description("CLI for Open Artifacts — self-hosted artifact hosting for AI agents").version("0.3.0");
9
10
  program
10
11
  .command("login")
11
12
  .description("Authorize this device via OAuth device flow and save credentials")
12
13
  .option("--server <url>", "Open Artifacts server URL", "http://localhost:3000")
13
- .option("--name <name>", "Name to register this agent as")
14
+ .option("--name <name>", "Name to register this agent/device as")
14
15
  .option("--scopes <scopes>", "Comma-separated scopes to request", "artifacts:read,artifacts:write,shares:write")
16
+ .option("--agent", "Issue an agent key locked to one team, instead of a personal key spanning all your teams")
15
17
  .action(async (opts) => {
16
18
  const scopes = String(opts.scopes).split(",").map((s) => s.trim());
17
19
  for (const scope of scopes) {
@@ -20,13 +22,24 @@ program
20
22
  process.exit(1);
21
23
  }
22
24
  }
23
- await login({ server: opts.server, name: opts.name, scopes });
25
+ await login({ server: opts.server, name: opts.name, scopes, agent: opts.agent });
24
26
  });
25
27
  program.command("whoami").description("Show the current credentials and verify they work").action(whoamiCommand);
28
+ program
29
+ .command("orgs")
30
+ .description("List the teams your key can act in, and which one is currently selected")
31
+ .option("--json", "Output raw JSON")
32
+ .action(orgsCommand);
33
+ program
34
+ .command("use <team>")
35
+ .description("Set the default team (by id or slug) for this project, or --global for this machine")
36
+ .option("--global", "Set the default for this machine instead of writing .oa.json in the project")
37
+ .action(useCommand);
26
38
  program
27
39
  .command("list")
28
- .description("List artifacts in your org")
40
+ .description("List artifacts in your team")
29
41
  .option("--json", "Output raw JSON")
42
+ .option("--org <team>", "Team id or slug (overrides the project/machine default)")
30
43
  .action(listCommand);
31
44
  program
32
45
  .command("push <file>")
@@ -38,6 +51,7 @@ program
38
51
  .option("--password <password>", "Create a password-protected share instead of a public one (implies --share)")
39
52
  .option("--message <message>", "Version message")
40
53
  .option("--json", "Output raw JSON")
54
+ .option("--org <team>", "Team id or slug to publish into (overrides the project/machine default)")
41
55
  .action((file, opts) => pushCommand(file, { ...opts, share: opts.share || !!opts.password }));
42
56
  program
43
57
  .command("get <id>")
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/org.js ADDED
@@ -0,0 +1,31 @@
1
+ import { findProjectConfig } from "./project-config.js";
2
+ /**
3
+ * Priority: --org flag > OA_ORG env > .oa.json found by walking up from cwd > a pre-0.3.0
4
+ * (agent-only) credentials file's locked org. Resolving to nothing isn't an error — the server
5
+ * auto-picks when a personal key's holder belongs to exactly one team, or returns `org_required`
6
+ * with the candidate list otherwise (see services/org-scope.ts on the server).
7
+ */
8
+ export function resolveOrg(opts) {
9
+ if (opts.flag)
10
+ return { orgId: opts.flag, source: "flag" };
11
+ const env = opts.env ?? process.env;
12
+ if (env.OA_ORG)
13
+ return { orgId: env.OA_ORG, source: "env" };
14
+ const project = findProjectConfig(opts.cwd);
15
+ if (project?.config.orgId) {
16
+ // An orgId only makes sense on the server it was written for. A mismatch would otherwise
17
+ // surface as an opaque "forbidden" from the API instead of a clear "wrong server" warning.
18
+ if (project.config.server && opts.creds?.server && project.config.server !== opts.creds.server) {
19
+ console.error(`Warning: ${project.path} was written for ${project.config.server}, not ${opts.creds.server} — ignoring its orgId.`);
20
+ }
21
+ else {
22
+ return { orgId: project.config.orgId, source: "project", configPath: project.path };
23
+ }
24
+ }
25
+ // A pre-0.3.0 credentials file has no `kind` and always carries the single org its agent key
26
+ // was locked to. A personal (kind: "user") key has no such single org to fall back to.
27
+ if (!opts.creds?.kind && opts.creds?.orgId)
28
+ return { orgId: opts.creds.orgId, source: "credentials" };
29
+ return { source: "none" };
30
+ }
31
+ //# sourceMappingURL=org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org.js","sourceRoot":"","sources":["../src/org.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAiBxD;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAoB;IAC7C,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE3D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAE5D,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,yFAAyF;QACzF,2FAA2F;QAC3F,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/F,OAAO,CAAC,KAAK,CAAC,YAAY,OAAO,CAAC,IAAI,oBAAoB,OAAO,CAAC,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,KAAK,CAAC,MAAM,wBAAwB,CAAC,CAAC;QACrI,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACtF,CAAC;IACH,CAAC;IAED,6FAA6F;IAC7F,uFAAuF;IACvF,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAEtG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ export const PROJECT_CONFIG_FILENAME = ".oa.json";
4
+ /** Walks up from `cwd` to the filesystem root looking for `.oa.json`, the same way git/eslint find their config. */
5
+ export function findProjectConfig(cwd = process.cwd()) {
6
+ let dir = cwd;
7
+ for (;;) {
8
+ const path = join(dir, PROJECT_CONFIG_FILENAME);
9
+ if (existsSync(path)) {
10
+ try {
11
+ return { path, config: JSON.parse(readFileSync(path, "utf8")) };
12
+ }
13
+ catch {
14
+ console.error(`Warning: ${path} is not valid JSON — ignoring it.`);
15
+ return null;
16
+ }
17
+ }
18
+ const parent = dirname(dir);
19
+ if (parent === dir)
20
+ return null; // reached the filesystem root
21
+ dir = parent;
22
+ }
23
+ }
24
+ /** Where a fresh `.oa.json` should be written: the nearest existing one, else the repo root, else cwd. */
25
+ export function projectConfigTarget(cwd = process.cwd()) {
26
+ const existing = findProjectConfig(cwd);
27
+ if (existing)
28
+ return existing.path;
29
+ let dir = cwd;
30
+ for (;;) {
31
+ if (existsSync(join(dir, ".git")))
32
+ return join(dir, PROJECT_CONFIG_FILENAME);
33
+ const parent = dirname(dir);
34
+ if (parent === dir)
35
+ break;
36
+ dir = parent;
37
+ }
38
+ return join(cwd, PROJECT_CONFIG_FILENAME);
39
+ }
40
+ /** Merges `patch` into the config at `path`, creating it if needed. */
41
+ export function writeProjectConfig(path, patch) {
42
+ let current = {};
43
+ if (existsSync(path)) {
44
+ try {
45
+ current = JSON.parse(readFileSync(path, "utf8"));
46
+ }
47
+ catch {
48
+ // Corrupt file holds no secrets worth preserving — just overwrite it.
49
+ }
50
+ }
51
+ writeFileSync(path, `${JSON.stringify({ ...current, ...patch }, null, 2)}\n`, "utf8");
52
+ }
53
+ //# sourceMappingURL=project-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-config.js","sourceRoot":"","sources":["../src/project-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,uBAAuB,GAAG,UAAU,CAAC;AAclD,oHAAoH;AACpH,MAAM,UAAU,iBAAiB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC3D,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;QAChD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,EAAE,CAAC;YACnF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,KAAK,CAAC,YAAY,IAAI,mCAAmC,CAAC,CAAC;gBACnE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAC/D,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,mBAAmB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC7D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC;IAEnC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;AAC5C,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,KAA6B;IAC5E,IAAI,OAAO,GAAkB,EAAE,CAAC;IAChC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;QACxE,CAAC;IACH,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACxF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emaxe/oa",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "CLI for Open Artifacts — publish HTML/Markdown/Mermaid/SVG content to a self-hosted artifact host and get back a shareable link.",
5
5
  "keywords": [
6
6
  "ai-agents",