@ekanos/cli 0.13.0 → 0.15.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 +25 -8
- package/dist/agents-api.d.ts +11 -2
- package/dist/agents-api.js +39 -3
- package/dist/agents-api.js.map +1 -1
- package/dist/apps-api.js +2 -2
- package/dist/apps-api.js.map +1 -1
- package/dist/auth/ekanos-api.d.ts +16 -2
- package/dist/auth/ekanos-api.js +101 -15
- package/dist/auth/ekanos-api.js.map +1 -1
- package/dist/auth/host-trust.d.ts +46 -0
- package/dist/auth/host-trust.js +79 -0
- package/dist/auth/host-trust.js.map +1 -0
- package/dist/auth/session.d.ts +10 -1
- package/dist/auth/session.js +28 -28
- package/dist/auth/session.js.map +1 -1
- package/dist/commands/agents-edit.d.ts +6 -2
- package/dist/commands/agents-edit.js +57 -26
- package/dist/commands/agents-edit.js.map +1 -1
- package/dist/commands/agents.d.ts +13 -2
- package/dist/commands/agents.js +140 -35
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/apps.d.ts +2 -0
- package/dist/commands/apps.js +16 -12
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/catalog.js +7 -6
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/knowledge.d.ts +19 -0
- package/dist/commands/knowledge.js +119 -27
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.js +30 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +9 -1
- package/dist/commands/logout.js +56 -7
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/publish.js +3 -3
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/reviewers.d.ts +2 -0
- package/dist/commands/reviewers.js +7 -3
- package/dist/commands/reviewers.js.map +1 -1
- package/dist/commands/routes.d.ts +2 -0
- package/dist/commands/routes.js +42 -9
- package/dist/commands/routes.js.map +1 -1
- package/dist/commands/runs.d.ts +13 -2
- package/dist/commands/runs.js +99 -16
- package/dist/commands/runs.js.map +1 -1
- package/dist/commands/scope-notice.d.ts +21 -0
- package/dist/commands/scope-notice.js +35 -0
- package/dist/commands/scope-notice.js.map +1 -0
- package/dist/commands/skills.d.ts +7 -1
- package/dist/commands/skills.js +80 -24
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/sources.d.ts +1 -1
- package/dist/commands/sources.js +126 -12
- package/dist/commands/sources.js.map +1 -1
- package/dist/commands/status.js +5 -4
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/team-agent-readiness.d.ts +49 -0
- package/dist/commands/team-agent-readiness.js +308 -0
- package/dist/commands/team-agent-readiness.js.map +1 -0
- package/dist/commands/team-agents-agents.d.ts +24 -3
- package/dist/commands/team-agents-agents.js +314 -35
- package/dist/commands/team-agents-agents.js.map +1 -1
- package/dist/commands/team-agents-mcp.js +32 -3
- package/dist/commands/team-agents-mcp.js.map +1 -1
- package/dist/commands/team-agents-triggers.js +230 -55
- package/dist/commands/team-agents-triggers.js.map +1 -1
- package/dist/commands/team-agents.d.ts +3 -1
- package/dist/commands/team-agents.js +27 -7
- package/dist/commands/team-agents.js.map +1 -1
- package/dist/commands/teams-channel-install.d.ts +24 -0
- package/dist/commands/teams-channel-install.js +94 -0
- package/dist/commands/teams-channel-install.js.map +1 -0
- package/dist/commands/teams-connect.d.ts +41 -0
- package/dist/commands/teams-connect.js +212 -57
- package/dist/commands/teams-connect.js.map +1 -1
- package/dist/commands/teams-events.d.ts +12 -0
- package/dist/commands/teams-events.js +138 -0
- package/dist/commands/teams-events.js.map +1 -0
- package/dist/commands/teams-onboard.d.ts +11 -3
- package/dist/commands/teams-onboard.js +60 -7
- package/dist/commands/teams-onboard.js.map +1 -1
- package/dist/commands/teams-overview.d.ts +11 -0
- package/dist/commands/teams-overview.js +160 -0
- package/dist/commands/teams-overview.js.map +1 -0
- package/dist/commands/teams-scope.d.ts +10 -0
- package/dist/commands/teams-scope.js +109 -0
- package/dist/commands/teams-scope.js.map +1 -0
- package/dist/commands/teams.d.ts +4 -2
- package/dist/commands/teams.js +113 -14
- package/dist/commands/teams.js.map +1 -1
- package/dist/commands/upgrade.js +12 -2
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/use.js +2 -2
- package/dist/commands/use.js.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/connections-api.js +1 -1
- package/dist/connections-api.js.map +1 -1
- package/dist/delegate.js +11 -4
- package/dist/delegate.js.map +1 -1
- package/dist/harness-scaffold.js +12 -0
- package/dist/harness-scaffold.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +682 -167
- package/dist/index.js.map +1 -1
- package/dist/knowledge-api.d.ts +46 -0
- package/dist/knowledge-api.js +32 -1
- package/dist/knowledge-api.js.map +1 -1
- package/dist/open-url.d.ts +16 -0
- package/dist/open-url.js +73 -0
- package/dist/open-url.js.map +1 -0
- package/dist/parse-argv.d.ts +2 -0
- package/dist/parse-argv.js.map +1 -1
- package/dist/publish-api.d.ts +2 -1
- package/dist/publish-api.js +4 -3
- package/dist/publish-api.js.map +1 -1
- package/dist/pull-write.d.ts +27 -0
- package/dist/pull-write.js +60 -0
- package/dist/pull-write.js.map +1 -0
- package/dist/routes-api.d.ts +3 -0
- package/dist/routes-api.js +9 -4
- package/dist/routes-api.js.map +1 -1
- package/dist/runs-api.d.ts +7 -1
- package/dist/runs-api.js +21 -6
- package/dist/runs-api.js.map +1 -1
- package/dist/safe-fs.d.ts +2 -0
- package/dist/safe-fs.js +12 -6
- package/dist/safe-fs.js.map +1 -1
- package/dist/secret-file.d.ts +17 -0
- package/dist/secret-file.js +69 -0
- package/dist/secret-file.js.map +1 -0
- package/dist/skills-api.d.ts +10 -2
- package/dist/skills-api.js +37 -2
- package/dist/skills-api.js.map +1 -1
- package/dist/source-products-api.d.ts +4 -0
- package/dist/source-products-api.js +14 -4
- package/dist/source-products-api.js.map +1 -1
- package/dist/source-target.js +2 -1
- package/dist/source-target.js.map +1 -1
- package/dist/sources-api.d.ts +2 -1
- package/dist/sources-api.js +3 -2
- package/dist/sources-api.js.map +1 -1
- package/dist/team-connect-api.d.ts +44 -2
- package/dist/team-connect-api.js +19 -7
- package/dist/team-connect-api.js.map +1 -1
- package/dist/teams-api.d.ts +41 -1
- package/dist/teams-api.js +95 -19
- package/dist/teams-api.js.map +1 -1
- package/dist/toolchain-api.d.ts +9 -0
- package/dist/toolchain-api.js +17 -2
- package/dist/toolchain-api.js.map +1 -1
- package/dist/toolchain-resolve.d.ts +3 -0
- package/dist/toolchain-resolve.js +15 -1
- package/dist/toolchain-resolve.js.map +1 -1
- package/dist/toolchain.d.ts +6 -0
- package/dist/toolchain.js +19 -0
- package/dist/toolchain.js.map +1 -1
- package/dist/update-notice.js +2 -1
- package/dist/update-notice.js.map +1 -1
- package/package.json +2 -2
- package/templates/AGENTS.md.tmpl +6 -1
- package/templates/claude-skill.md.tmpl +5 -0
- package/templates/package.json.tmpl +4 -4
- package/templates/skills/build-agent/SKILL.md +104 -17
- package/templates/skills/build-agent/references/agent-json.md +4 -2
- package/templates/skills/build-agent/references/rollout.md +23 -4
- package/templates/skills/build-agent/references/set-up-an-integration.md +55 -7
- package/templates/skills/build-agent/references/skills.md +20 -1
- package/templates/skills/build-agent/references/triggers.md +47 -11
- package/templates/skills/build-integration/references/widget-design.md +3 -3
- package/templates/skills/ekanos-platform/SKILL.md +45 -16
- package/templates/skills/polish-widgets/references/patterns.md +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-products-api.js","sourceRoot":"","sources":["../src/source-products-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\n\nimport { request } from './auth/ekanos-api';\nimport {\n authRequiredError,\n forbiddenError,\n invalidStateError,\n networkError,\n notFoundError,\n usageError,\n} from './errors';\n\n/**\n * The CLI's client for a Source's products (`ekanos sources products`).\n *\n * GET /api/partner/sources/products?source=<slug|id>\n * → { source, products: [{ slug, name, kind, enabled, lever, registered }], canEnable }\n * PUT /api/partner/sources/products/<product>?source=<slug|id> enable\n * DELETE /api/partner/sources/products/<product>?source=<slug|id> disable\n * → { source, product, changed }\n *\n * → 401 / 3xx refresh once and retry\n * → 403 SUPER_ADMIN_REQUIRED enabling is a super-admin grant, which an\n * `ekanos login` session never carries\n * → 409 REFUSED a dependency or demo-only guard refused\n *\n * The shapes are read here rather than from `@ekanos/integration-schema`, so\n * this CLI works against a host without a schema release.\n */\n\nconst SourceRefSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string().nullable(),\n});\n\nexport const SourceProductSchema = z.object({\n slug: z.string(),\n name: z.string(),\n kind: z.enum(['experience', 'integration']),\n enabled: z.boolean(),\n lever: z.enum(['flag', 'plan', 'entitlement']),\n registered: z.boolean(),\n});\nexport type SourceProduct = z.infer<typeof SourceProductSchema>;\n\nconst ListSchema = z.object({\n source: SourceRefSchema,\n products: z.array(SourceProductSchema),\n canEnable: z.boolean(),\n});\nconst ChangeSchema = z.object({\n source: SourceRefSchema,\n product: SourceProductSchema,\n changed: z.boolean(),\n});\n\nexport type SourceProductsApiResult<T> =\n | { status: 'ok'; data: T }\n | { status: 'unauthorized' };\n\nexport function listSourceProducts(\n host: string,\n token: string,\n source: string,\n) {\n return call(host, token, ListSchema, {\n method: 'GET',\n path: `/api/partner/sources/products?${new URLSearchParams({ source })}`,\n });\n}\n\nexport function setSourceProduct(\n host: string,\n token: string,\n input: { source: string; product: string; enabled: boolean },\n) {\n return call(host, token, ChangeSchema, {\n method: input.enabled ? 'PUT' : 'DELETE',\n path: `/api/partner/sources/products/${encodeURIComponent(input.product)}?${new URLSearchParams({ source: input.source })}`,\n });\n}\n\nasync function call<T>(\n host: string,\n accessToken: string,\n schema: z.ZodType<T>,\n init: { method: 'GET' | 'PUT' | 'DELETE'; path: string },\n): Promise<SourceProductsApiResult<T>> {\n const response = await request(`${host}${init.path}`, {\n method: init.method,\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (\n response.status === 401 ||\n (response.status >= 300 && response.status < 400)\n ) {\n return { status: 'unauthorized' };\n }\n\n const body = await readOptionalJson(response);\n const code = typeof body.code === 'string' ? body.code : null;\n const message =\n typeof body.error === 'string' && body.error ? body.error : null;\n\n if (response.status === 403 && code === 'MFA_REQUIRED') {\n throw authRequiredError(\n message ?? `${host} requires multi-factor authentication.`,\n 'Complete MFA in the browser, then run \"ekanos login\" again.',\n );\n }\n if (response.status === 403 && code === 'SUPER_ADMIN_REQUIRED') {\n throw forbiddenError(\n message ?? 'Only a super-admin enables a product for a Source.',\n 'A super-admin does it in the browser: /admin/sources → the Source → Products (Experiences are switched on the same page).',\n );\n }\n if (response.status === 403) {\n throw forbiddenError(\n message ?? 'Not permitted on this Source.',\n 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 404) {\n throw notFoundError(\n message ?? 'Not found.',\n code === 'PRODUCT_NOT_FOUND'\n ? '\"ekanos sources products\" lists the catalog.'\n : 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 409) {\n throw invalidStateError(\n message ?? 'The host refused the change.',\n '\"ekanos sources products\" shows what this Source has.',\n );\n }\n if (response.status === 400) {\n throw usageError(\n message ?? 'The host refused the request.',\n 'See \"ekanos sources --help\".',\n );\n }\n if (!response.ok) {\n throw networkError(\n `${host}${init.path.split('?')[0]} responded ${response.status}.`,\n response.status >= 500\n ? 'The Ekanos deployment returned a server error. Retry shortly.'\n : 'Confirm the host runs a build that includes the source products routes.',\n );\n }\n\n const parsed = schema.safeParse(body.data);\n if (!parsed.success) {\n throw networkError(\n `${host}/api/partner/sources/products answered in a shape this CLI does not read.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the source products contract.',\n );\n }\n return { status: 'ok', data: parsed.data };\n}\n\nasync function readOptionalJson(\n response: Response,\n): Promise<Record<string, unknown>> {\n try {\n const parsed: unknown = await response.json();\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"source-products-api.js","sourceRoot":"","sources":["../src/source-products-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\n\nimport { request } from './auth/ekanos-api';\nimport {\n authRequiredError,\n forbiddenError,\n invalidStateError,\n networkError,\n notFoundError,\n usageError,\n} from './errors';\n\n/**\n * The CLI's client for a Source's products (`ekanos sources products`).\n *\n * GET /api/partner/sources/products?source=<slug|id>\n * → { source, products: [{ slug, name, kind, enabled, lever, registered, owned }],\n * canEnable, canEnableOwned }\n * PUT /api/partner/sources/products/<product>?source=<slug|id> enable\n * DELETE /api/partner/sources/products/<product>?source=<slug|id> disable\n * → { source, product, changed }\n *\n * → 401 / 3xx refresh once and retry\n * → 403 SOURCE_ADMIN_REQUIRED no Source admin seat on the Source\n * → 403 SUPER_ADMIN_REQUIRED not an integration the Source built: a\n * super-admin grant, which an `ekanos login`\n * session never carries\n * → 409 REFUSED a dependency or demo-only guard refused\n *\n * The shapes are read here rather than from `@ekanos/integration-schema`, so\n * this CLI works against a host without a schema release.\n */\n\nconst SourceRefSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string().nullable(),\n});\n\nexport const SourceProductSchema = z.object({\n slug: z.string(),\n name: z.string(),\n kind: z.enum(['experience', 'integration']),\n enabled: z.boolean(),\n lever: z.enum(['flag', 'plan', 'entitlement']),\n registered: z.boolean(),\n /** The Source built it, so its Source admin may switch it. Absent on an\n * older host, which allowed no Source admin to. */\n owned: z.boolean().optional().default(false),\n});\nexport type SourceProduct = z.infer<typeof SourceProductSchema>;\n\nconst ListSchema = z.object({\n source: SourceRefSchema,\n products: z.array(SourceProductSchema),\n canEnable: z.boolean(),\n canEnableOwned: z.boolean().optional().default(false),\n});\nconst ChangeSchema = z.object({\n source: SourceRefSchema,\n product: SourceProductSchema,\n changed: z.boolean(),\n});\n\nexport type SourceProductsApiResult<T> =\n | { status: 'ok'; data: T }\n | { status: 'unauthorized' };\n\nexport function listSourceProducts(\n host: string,\n token: string,\n source: string,\n) {\n return call(host, token, ListSchema, {\n method: 'GET',\n path: `/api/partner/sources/products?${new URLSearchParams({ source })}`,\n });\n}\n\nexport function setSourceProduct(\n host: string,\n token: string,\n input: { source: string; product: string; enabled: boolean },\n) {\n return call(host, token, ChangeSchema, {\n method: input.enabled ? 'PUT' : 'DELETE',\n path: `/api/partner/sources/products/${encodeURIComponent(input.product)}?${new URLSearchParams({ source: input.source })}`,\n });\n}\n\nasync function call<T>(\n host: string,\n accessToken: string,\n schema: z.ZodType<T>,\n init: { method: 'GET' | 'PUT' | 'DELETE'; path: string },\n): Promise<SourceProductsApiResult<T>> {\n const response = await request(`${host}${init.path}`, {\n method: init.method,\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (\n response.status === 401 ||\n (response.status >= 300 && response.status < 400)\n ) {\n return { status: 'unauthorized' };\n }\n\n const body = await readOptionalJson(response);\n const code = typeof body.code === 'string' ? body.code : null;\n const message =\n typeof body.error === 'string' && body.error ? body.error : null;\n\n if (response.status === 403 && code === 'MFA_REQUIRED') {\n throw authRequiredError(\n message ?? `${host} requires multi-factor authentication.`,\n 'Complete MFA in the browser, then run \"ekanos login\" again.',\n );\n }\n if (response.status === 403 && code === 'SUPER_ADMIN_REQUIRED') {\n throw forbiddenError(\n message ?? 'Only a super-admin enables this product for a Source.',\n 'A Source admin switches only the integrations their Source built. Anything else a super-admin does in the browser: /admin/sources → the Source → Products (Experiences are switched on the same page).',\n );\n }\n if (response.status === 403 && code === 'SOURCE_ADMIN_REQUIRED') {\n throw forbiddenError(\n message ?? 'Switching a product needs a Source admin seat on the Source.',\n 'Run \"ekanos sources\" to see your seats; a Source admin grants the seat.',\n );\n }\n if (response.status === 403) {\n throw forbiddenError(\n message ?? 'Not permitted on this Source.',\n 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 404) {\n throw notFoundError(\n message ?? 'Not found.',\n code === 'PRODUCT_NOT_FOUND'\n ? '\"ekanos sources products\" lists the catalog.'\n : 'Run \"ekanos sources\" to list the sources you hold a seat on.',\n );\n }\n if (response.status === 409) {\n throw invalidStateError(\n message ?? 'The host refused the change.',\n '\"ekanos sources products\" shows what this Source has.',\n );\n }\n if (response.status === 400) {\n throw usageError(\n message ?? 'The host refused the request.',\n 'See \"ekanos sources --help\".',\n );\n }\n if (!response.ok) {\n throw networkError(\n `${host}${init.path.split('?')[0]} responded ${response.status}.`,\n response.status >= 500\n ? 'The Ekanos deployment returned a server error. Retry shortly.'\n : 'Confirm the host runs a build that includes the source products routes.',\n );\n }\n\n const parsed = schema.safeParse(body.data);\n if (!parsed.success) {\n throw networkError(\n `${host}/api/partner/sources/products answered in a shape this CLI does not read.`,\n 'Run \"ekanos upgrade\" — the CLI and the host disagree on the source products contract.',\n );\n }\n return { status: 'ok', data: parsed.data };\n}\n\nasync function readOptionalJson(\n response: Response,\n): Promise<Record<string, unknown>> {\n try {\n const parsed: unknown = await response.json();\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n"]}
|
package/dist/source-target.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loginHint } from './auth/host-trust.js';
|
|
1
2
|
import { readActiveSource } from './commands/sources.js';
|
|
2
3
|
import { authRequiredError, validationError } from './errors.js';
|
|
3
4
|
import { fetchSeatsWithOneRefresh } from './seats.js';
|
|
@@ -14,7 +15,7 @@ export async function resolveSourceTarget(env, session, args) {
|
|
|
14
15
|
return { source: named, session };
|
|
15
16
|
const seats = await fetchSeatsWithOneRefresh(env, session);
|
|
16
17
|
if (seats.status !== 'ok') {
|
|
17
|
-
throw authRequiredError(`The session for ${env.host} could not list your sources.`,
|
|
18
|
+
throw authRequiredError(`The session for ${env.host} could not list your sources.`, loginHint(env));
|
|
18
19
|
}
|
|
19
20
|
if (seats.sources.length === 1) {
|
|
20
21
|
return { source: seats.sources[0].slug, session: seats.session };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-target.js","sourceRoot":"","sources":["../src/source-target.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"source-target.js","sourceRoot":"","sources":["../src/source-target.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAoB,EACpB,OAAsB,EACtB,IAAsC;;IAEtC,MAAM,KAAK,GAAG,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,IAAI,EAAE,KAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChE,IAAI,KAAK;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAE7C,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,iBAAiB,CACrB,mBAAmB,GAAG,CAAC,IAAI,+BAA+B,EAC1D,SAAS,CAAC,GAAG,CAAC,CACf,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACpE,CAAC;IAED,MAAM,eAAe,CACnB,6CAA6C;QAC3C,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YACzB,CAAC,CAAC,yBAAyB;YAC3B,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAC9D,yDAAyD,CAC1D,CAAC;AACJ,CAAC","sourcesContent":["import type { StoredSession } from './auth/credential-store';\nimport { loginHint } from './auth/host-trust';\nimport type { AuthEnvironment } from './auth/session';\nimport { readActiveSource } from './commands/sources';\nimport { authRequiredError, validationError } from './errors';\nimport { fetchSeatsWithOneRefresh } from './seats';\n\n/**\n * Which Source a Source-scoped read or write (`catalog`, `agents`) is about:\n * `--source`, else `source` in ekanos.json, else the caller's only seat.\n * Works outside a project. With several seats and nothing named, it refuses\n * rather than guessing.\n */\nexport async function resolveSourceTarget(\n env: AuthEnvironment,\n session: StoredSession,\n args: { source?: string; dir: string },\n): Promise<{ source: string; session: StoredSession }> {\n const named = args.source?.trim() || readActiveSource(args.dir);\n if (named) return { source: named, session };\n\n const seats = await fetchSeatsWithOneRefresh(env, session);\n if (seats.status !== 'ok') {\n throw authRequiredError(\n `The session for ${env.host} could not list your sources.`,\n loginHint(env),\n );\n }\n if (seats.sources.length === 1) {\n return { source: seats.sources[0]!.slug, session: seats.session };\n }\n\n throw validationError(\n 'Which Source? This account holds a seat on ' +\n (seats.sources.length === 0\n ? 'no source on this host.'\n : `${seats.sources.map((seat) => seat.slug).join(', ')}.`),\n 'Pass \"--source <slug>\", or set \"source\" in ekanos.json.',\n );\n}\n"]}
|
package/dist/sources-api.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AuthEnvironment } from './auth/session.js';
|
|
1
2
|
/**
|
|
2
3
|
* The CLI's client for the Ekanos source-seat visibility route.
|
|
3
4
|
*
|
|
@@ -41,4 +42,4 @@ export type FetchSourceSeatsResult = {
|
|
|
41
42
|
*/
|
|
42
43
|
export declare function fetchSourceSeats(host: string, accessToken: string): Promise<FetchSourceSeatsResult>;
|
|
43
44
|
/** Guard for the "still unauthorized after one refresh" terminal case. */
|
|
44
|
-
export declare function stillUnauthorizedSourceSeats(
|
|
45
|
+
export declare function stillUnauthorizedSourceSeats(env: AuthEnvironment): never;
|
package/dist/sources-api.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { request } from './auth/ekanos-api.js';
|
|
2
|
+
import { loginHint } from './auth/host-trust.js';
|
|
2
3
|
import { authRequiredError, networkError } from './errors.js';
|
|
3
4
|
/**
|
|
4
5
|
* List the sources the caller holds a seat on (any role). Authorization is
|
|
@@ -43,8 +44,8 @@ export async function fetchSourceSeats(host, accessToken) {
|
|
|
43
44
|
return { status: 'ok', sources };
|
|
44
45
|
}
|
|
45
46
|
/** Guard for the "still unauthorized after one refresh" terminal case. */
|
|
46
|
-
export function stillUnauthorizedSourceSeats(
|
|
47
|
-
throw authRequiredError(`The session for ${host} could not authorize the source seat lookup.`,
|
|
47
|
+
export function stillUnauthorizedSourceSeats(env) {
|
|
48
|
+
throw authRequiredError(`The session for ${env.host} could not authorize the source seat lookup.`, loginHint(env));
|
|
48
49
|
}
|
|
49
50
|
async function readOptionalJson(response) {
|
|
50
51
|
try {
|
package/dist/sources-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources-api.js","sourceRoot":"","sources":["../src/sources-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAqC3D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,WAAmB;;IAEnB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,sBAAsB,EAAE;QAC5D,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,aAAa,EAAE,UAAU,WAAW,EAAE;SACvC;KACF,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE9C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,iBAAiB,OACrB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,mCACb,GAAG,IAAI,yDAAyD,EAClE,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,YAAY,CAChB,GAAG,IAAI,kCAAkC,QAAQ,CAAC,MAAM,GAAG,EAC3D,QAAQ,CAAC,MAAM,IAAI,GAAG;YACpB,CAAC,CAAC,mEAAmE;gBACjE,8CAA8C;YAClD,CAAC,CAAC,gEAAgE;gBAC9D,qCAAqC,CAC5C,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,OAAC,IAAI,CAAC,IAAI,mCAAI,EAAE,CAA4B,CAAC;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7D,MAAM,OAAO,GAAG,IAAI;SACjB,MAAM,CACL,CAAC,GAAG,EAAkC,EAAE,CACtC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAC1C;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,sBAAC,CAAC;QACb,EAAE,QAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,EAAE;QACrB,IAAI,QAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE;QACzB,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAC7B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;YACtE,CAAC,CAAC,EAAE;KACP,CAAC,GAAA,CAAC,CAAC;IAEN,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,4BAA4B,CAAC,
|
|
1
|
+
{"version":3,"file":"sources-api.js","sourceRoot":"","sources":["../src/sources-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAqC3D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,WAAmB;;IAEnB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,sBAAsB,EAAE;QAC5D,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,aAAa,EAAE,UAAU,WAAW,EAAE;SACvC;KACF,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE9C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,iBAAiB,OACrB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,mCACb,GAAG,IAAI,yDAAyD,EAClE,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,YAAY,CAChB,GAAG,IAAI,kCAAkC,QAAQ,CAAC,MAAM,GAAG,EAC3D,QAAQ,CAAC,MAAM,IAAI,GAAG;YACpB,CAAC,CAAC,mEAAmE;gBACjE,8CAA8C;YAClD,CAAC,CAAC,gEAAgE;gBAC9D,qCAAqC,CAC5C,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,OAAC,IAAI,CAAC,IAAI,mCAAI,EAAE,CAA4B,CAAC;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7D,MAAM,OAAO,GAAG,IAAI;SACjB,MAAM,CACL,CAAC,GAAG,EAAkC,EAAE,CACtC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAC1C;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,sBAAC,CAAC;QACb,EAAE,QAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,EAAE;QACrB,IAAI,QAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,EAAE;QACzB,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAC7B,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;YACtE,CAAC,CAAC,EAAE;KACP,CAAC,GAAA,CAAC,CAAC;IAEN,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,4BAA4B,CAAC,GAAoB;IAC/D,MAAM,iBAAiB,CACrB,mBAAmB,GAAG,CAAC,IAAI,8CAA8C,EACzE,SAAS,CAAC,GAAG,CAAC,CACf,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,QAAkB;IAElB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE9C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAClD,CAAC,CAAE,MAAkC;YACrC,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;eAAO,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC","sourcesContent":["import { request } from './auth/ekanos-api';\nimport { loginHint } from './auth/host-trust';\nimport type { AuthEnvironment } from './auth/session';\nimport { authRequiredError, networkError } from './errors';\n\n/**\n * The CLI's client for the Ekanos source-seat visibility route.\n *\n * ---------------------------------------------------------------------------\n * WIRE CONTRACT — the seam between this package and the Ekanos web app.\n *\n * The server side is the host's `/api/partner/sources` route. As with the\n * auth routes and `publish-api.ts`, the two halves are coupled only by\n * HTTP; tests stub `fetch`, never the route.\n *\n * GET /api/partner/sources [Authorization: Bearer <access_token>]\n * → 200 { ok: true, data: { sources: [{ id, slug, name, roles }] } }\n * roles is a non-empty array of \"developer\" | \"source_admin\", sorted; sources\n * is sorted by slug. Empty array means no seats anywhere.\n * → 401 { error, code: \"AUTH_REQUIRED\" } token absent or expired —\n * refresh once and retry\n * → 403 { error, code: \"MFA_REQUIRED\" }\n * → 3xx treated as 401 (an\n * auth-gated Ekanos page\n * answers 307)\n * ---------------------------------------------------------------------------\n */\n\nexport interface SourceSeat {\n id: string;\n slug: string;\n name: string | null;\n roles: string[];\n}\n\nexport type FetchSourceSeatsResult =\n | { status: 'ok'; sources: SourceSeat[] }\n /** The bearer token did not authenticate — refresh and retry, once. */\n | { status: 'unauthorized' };\n\n/**\n * List the sources the caller holds a seat on (any role). Authorization is\n * entirely server-side (RLS on `source_memberships`): there is no client-side\n * filter to get wrong here.\n */\nexport async function fetchSourceSeats(\n host: string,\n accessToken: string,\n): Promise<FetchSourceSeatsResult> {\n const response = await request(`${host}/api/partner/sources`, {\n method: 'GET',\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (response.status === 401 || isRedirect(response.status)) {\n return { status: 'unauthorized' };\n }\n\n const body = await readOptionalJson(response);\n\n if (response.status === 403) {\n throw authRequiredError(\n str(body.error) ??\n `${host} requires multi-factor authentication for this account.`,\n `Complete MFA in the browser, then run \"ekanos login\" again.`,\n );\n }\n\n if (!response.ok) {\n throw networkError(\n `${host}/api/partner/sources responded ${response.status}.`,\n response.status >= 500\n ? `The Ekanos deployment returned a server error. Retry shortly; if ` +\n `it persists, report it with the status code.`\n : `Confirm the host is an Ekanos deployment running a build that ` +\n `includes the partner sources route.`,\n );\n }\n\n const data = (body.data ?? {}) as Record<string, unknown>;\n const rows = Array.isArray(data.sources) ? data.sources : [];\n\n const sources = rows\n .filter(\n (row): row is Record<string, unknown> =>\n typeof row === 'object' && row !== null,\n )\n .map((row) => ({\n id: str(row.id) ?? '',\n slug: str(row.slug) ?? '',\n name: str(row.name),\n roles: Array.isArray(row.roles)\n ? row.roles.filter((role): role is string => typeof role === 'string')\n : [],\n }));\n\n return { status: 'ok', sources };\n}\n\n/** Guard for the \"still unauthorized after one refresh\" terminal case. */\nexport function stillUnauthorizedSourceSeats(env: AuthEnvironment): never {\n throw authRequiredError(\n `The session for ${env.host} could not authorize the source seat lookup.`,\n loginHint(env),\n );\n}\n\nasync function readOptionalJson(\n response: Response,\n): Promise<Record<string, unknown>> {\n try {\n const parsed: unknown = await response.json();\n\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction isRedirect(status: number): boolean {\n return status >= 300 && status < 400;\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n"]}
|
|
@@ -4,10 +4,10 @@ import { type TeamsApiResult } from './teams-api.js';
|
|
|
4
4
|
* The CLI's client for connecting a product for a team (`ekanos teams
|
|
5
5
|
* connect`), for the team's Source admin.
|
|
6
6
|
*
|
|
7
|
-
* GET /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>[&as=<email>]
|
|
7
|
+
* GET /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>[&as=<email>][&connection=<id>]
|
|
8
8
|
* → { plan }
|
|
9
9
|
* POST /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>
|
|
10
|
-
* { as?, fields? }
|
|
10
|
+
* { as?, fields?, connection? }
|
|
11
11
|
* → { plan, result: "activated" } fields / no-fields
|
|
12
12
|
* → { plan, result: "consent", authorizeUrl, expiresAt } oauth
|
|
13
13
|
*
|
|
@@ -38,6 +38,7 @@ export declare const TeamConnectPlanSchema: z.ZodObject<{
|
|
|
38
38
|
team: "team";
|
|
39
39
|
user: "user";
|
|
40
40
|
}>;
|
|
41
|
+
connectionId: z.ZodOptional<z.ZodString>;
|
|
41
42
|
mode: z.ZodEnum<{
|
|
42
43
|
browser: "browser";
|
|
43
44
|
fields: "fields";
|
|
@@ -66,6 +67,15 @@ export declare const TeamConnectPlanSchema: z.ZodObject<{
|
|
|
66
67
|
connected: z.ZodBoolean;
|
|
67
68
|
connectedAt: z.ZodNullable<z.ZodString>;
|
|
68
69
|
connectUrl: z.ZodString;
|
|
70
|
+
productScope: z.ZodOptional<z.ZodObject<{
|
|
71
|
+
state: z.ZodEnum<{
|
|
72
|
+
locked_out: "locked_out";
|
|
73
|
+
scoped: "scoped";
|
|
74
|
+
unscoped: "unscoped";
|
|
75
|
+
}>;
|
|
76
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
77
|
+
hidden: z.ZodBoolean;
|
|
78
|
+
}, z.core.$strip>>;
|
|
69
79
|
}, z.core.$strip>;
|
|
70
80
|
export type TeamConnectPlan = z.infer<typeof TeamConnectPlanSchema>;
|
|
71
81
|
declare const ShowSchema: z.ZodObject<{
|
|
@@ -91,6 +101,7 @@ declare const ShowSchema: z.ZodObject<{
|
|
|
91
101
|
team: "team";
|
|
92
102
|
user: "user";
|
|
93
103
|
}>;
|
|
104
|
+
connectionId: z.ZodOptional<z.ZodString>;
|
|
94
105
|
mode: z.ZodEnum<{
|
|
95
106
|
browser: "browser";
|
|
96
107
|
fields: "fields";
|
|
@@ -119,6 +130,15 @@ declare const ShowSchema: z.ZodObject<{
|
|
|
119
130
|
connected: z.ZodBoolean;
|
|
120
131
|
connectedAt: z.ZodNullable<z.ZodString>;
|
|
121
132
|
connectUrl: z.ZodString;
|
|
133
|
+
productScope: z.ZodOptional<z.ZodObject<{
|
|
134
|
+
state: z.ZodEnum<{
|
|
135
|
+
locked_out: "locked_out";
|
|
136
|
+
scoped: "scoped";
|
|
137
|
+
unscoped: "unscoped";
|
|
138
|
+
}>;
|
|
139
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
140
|
+
hidden: z.ZodBoolean;
|
|
141
|
+
}, z.core.$strip>>;
|
|
122
142
|
}, z.core.$strip>;
|
|
123
143
|
}, z.core.$strip>;
|
|
124
144
|
declare const StartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -144,6 +164,7 @@ declare const StartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
144
164
|
team: "team";
|
|
145
165
|
user: "user";
|
|
146
166
|
}>;
|
|
167
|
+
connectionId: z.ZodOptional<z.ZodString>;
|
|
147
168
|
mode: z.ZodEnum<{
|
|
148
169
|
browser: "browser";
|
|
149
170
|
fields: "fields";
|
|
@@ -172,6 +193,15 @@ declare const StartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
172
193
|
connected: z.ZodBoolean;
|
|
173
194
|
connectedAt: z.ZodNullable<z.ZodString>;
|
|
174
195
|
connectUrl: z.ZodString;
|
|
196
|
+
productScope: z.ZodOptional<z.ZodObject<{
|
|
197
|
+
state: z.ZodEnum<{
|
|
198
|
+
locked_out: "locked_out";
|
|
199
|
+
scoped: "scoped";
|
|
200
|
+
unscoped: "unscoped";
|
|
201
|
+
}>;
|
|
202
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
203
|
+
hidden: z.ZodBoolean;
|
|
204
|
+
}, z.core.$strip>>;
|
|
175
205
|
}, z.core.$strip>;
|
|
176
206
|
result: z.ZodLiteral<"activated">;
|
|
177
207
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -197,6 +227,7 @@ declare const StartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
197
227
|
team: "team";
|
|
198
228
|
user: "user";
|
|
199
229
|
}>;
|
|
230
|
+
connectionId: z.ZodOptional<z.ZodString>;
|
|
200
231
|
mode: z.ZodEnum<{
|
|
201
232
|
browser: "browser";
|
|
202
233
|
fields: "fields";
|
|
@@ -225,6 +256,15 @@ declare const StartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
225
256
|
connected: z.ZodBoolean;
|
|
226
257
|
connectedAt: z.ZodNullable<z.ZodString>;
|
|
227
258
|
connectUrl: z.ZodString;
|
|
259
|
+
productScope: z.ZodOptional<z.ZodObject<{
|
|
260
|
+
state: z.ZodEnum<{
|
|
261
|
+
locked_out: "locked_out";
|
|
262
|
+
scoped: "scoped";
|
|
263
|
+
unscoped: "unscoped";
|
|
264
|
+
}>;
|
|
265
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
266
|
+
hidden: z.ZodBoolean;
|
|
267
|
+
}, z.core.$strip>>;
|
|
228
268
|
}, z.core.$strip>;
|
|
229
269
|
result: z.ZodLiteral<"consent">;
|
|
230
270
|
authorizeUrl: z.ZodString;
|
|
@@ -235,6 +275,8 @@ interface Target {
|
|
|
235
275
|
source: string;
|
|
236
276
|
team: string;
|
|
237
277
|
product: string;
|
|
278
|
+
/** A named OAuth connection (`agent`); the main one when absent. */
|
|
279
|
+
connection?: string;
|
|
238
280
|
}
|
|
239
281
|
export declare function showTeamConnect(host: string, accessToken: string, target: Target, asEmail?: string): Promise<TeamsApiResult<z.infer<typeof ShowSchema>>>;
|
|
240
282
|
export declare function startTeamConnect(host: string, accessToken: string, target: Target, body: {
|
package/dist/team-connect-api.js
CHANGED
|
@@ -4,10 +4,10 @@ import { call } from './teams-api.js';
|
|
|
4
4
|
* The CLI's client for connecting a product for a team (`ekanos teams
|
|
5
5
|
* connect`), for the team's Source admin.
|
|
6
6
|
*
|
|
7
|
-
* GET /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>[&as=<email>]
|
|
7
|
+
* GET /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>[&as=<email>][&connection=<id>]
|
|
8
8
|
* → { plan }
|
|
9
9
|
* POST /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>
|
|
10
|
-
* { as?, fields? }
|
|
10
|
+
* { as?, fields?, connection? }
|
|
11
11
|
* → { plan, result: "activated" } fields / no-fields
|
|
12
12
|
* → { plan, result: "consent", authorizeUrl, expiresAt } oauth
|
|
13
13
|
*
|
|
@@ -29,6 +29,8 @@ export const TeamConnectPlanSchema = z.object({
|
|
|
29
29
|
kind: z.enum(['experience', 'integration']).nullable(),
|
|
30
30
|
}),
|
|
31
31
|
scope: z.enum(['team', 'user']),
|
|
32
|
+
/** The OAuth connection the plan is for; absent from an older host (`default`). */
|
|
33
|
+
connectionId: z.string().optional(),
|
|
32
34
|
mode: z.enum([
|
|
33
35
|
'unsupported',
|
|
34
36
|
'not-entitled',
|
|
@@ -59,6 +61,17 @@ export const TeamConnectPlanSchema = z.object({
|
|
|
59
61
|
connected: z.boolean(),
|
|
60
62
|
connectedAt: z.string().nullable(),
|
|
61
63
|
connectUrl: z.string(),
|
|
64
|
+
/**
|
|
65
|
+
* Whether the team's product scopes hide the product from it in the app.
|
|
66
|
+
* Absent from an older host.
|
|
67
|
+
*/
|
|
68
|
+
productScope: z
|
|
69
|
+
.object({
|
|
70
|
+
state: z.enum(['unscoped', 'scoped', 'locked_out']),
|
|
71
|
+
scopes: z.array(z.string()),
|
|
72
|
+
hidden: z.boolean(),
|
|
73
|
+
})
|
|
74
|
+
.optional(),
|
|
62
75
|
});
|
|
63
76
|
const ShowSchema = z.object({ plan: TeamConnectPlanSchema });
|
|
64
77
|
const StartSchema = z.discriminatedUnion('result', [
|
|
@@ -74,10 +87,9 @@ function connectPath(target) {
|
|
|
74
87
|
return `/api/partner/teams/${encodeURIComponent(target.team)}/integrations/${encodeURIComponent(target.product)}/connect`;
|
|
75
88
|
}
|
|
76
89
|
export function showTeamConnect(host, accessToken, target, asEmail) {
|
|
77
|
-
// `call` puts `source` in the query;
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
: connectPath(target);
|
|
90
|
+
// `call` puts `source` in the query; the rest ride in the path's own query.
|
|
91
|
+
const query = new URLSearchParams(Object.assign(Object.assign({}, (asEmail ? { as: asEmail } : {})), (target.connection ? { connection: target.connection } : {}))).toString();
|
|
92
|
+
const path = query ? `${connectPath(target)}?${query}` : connectPath(target);
|
|
81
93
|
return call(host, accessToken, ShowSchema, {
|
|
82
94
|
method: 'GET',
|
|
83
95
|
path,
|
|
@@ -89,7 +101,7 @@ export function startTeamConnect(host, accessToken, target, body) {
|
|
|
89
101
|
method: 'POST',
|
|
90
102
|
path: connectPath(target),
|
|
91
103
|
source: target.source,
|
|
92
|
-
body,
|
|
104
|
+
body: target.connection ? Object.assign(Object.assign({}, body), { connection: target.connection }) : body,
|
|
93
105
|
});
|
|
94
106
|
}
|
|
95
107
|
//# sourceMappingURL=team-connect-api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-connect-api.js","sourceRoot":"","sources":["../src/team-connect-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAuB,IAAI,EAAE,MAAM,aAAa,CAAC;AAExD;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC5B,CAAC;IACF,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACtD,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE;KACvD,CAAC;IACF,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;QACX,aAAa;QACb,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,OAAO;QACP,QAAQ;QACR,WAAW;QACX,SAAS;KACV,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,KAAK,CACb,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;QACtB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC,CACH;IACD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;KACtB,CAAC;SACD,QAAQ,EAAE;IACb,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IACtB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"team-connect-api.js","sourceRoot":"","sources":["../src/team-connect-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\n\nimport { type TeamsApiResult, call } from './teams-api';\n\n/**\n * The CLI's client for connecting a product for a team (`ekanos teams\n * connect`), for the team's Source admin.\n *\n * GET /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>[&as=<email>][&connection=<id>]\n * → { plan }\n * POST /api/partner/teams/<team>/integrations/<product>/connect?source=<slug>\n * { as?, fields?, connection? }\n * → { plan, result: \"activated\" } fields / no-fields\n * → { plan, result: \"consent\", authorizeUrl, expiresAt } oauth\n *\n * The plan's `mode`, decided by the host, says how the product is\n * connected. The shapes are read here rather than from\n * `@ekanos/integration-schema`, so this CLI works against a host without a\n * schema release.\n */\n\nexport const TeamConnectPlanSchema = z.object({\n source: z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string().nullable(),\n }),\n team: z.object({ slug: z.string(), name: z.string() }),\n product: z.object({\n slug: z.string(),\n name: z.string(),\n kind: z.enum(['experience', 'integration']).nullable(),\n }),\n scope: z.enum(['team', 'user']),\n /** The OAuth connection the plan is for; absent from an older host (`default`). */\n connectionId: z.string().optional(),\n mode: z.enum([\n 'unsupported',\n 'not-entitled',\n 'not-self-serve',\n 'works-as-shipped',\n 'oauth',\n 'fields',\n 'no-fields',\n 'browser',\n ]),\n reason: z.string().nullable(),\n fields: z.array(\n z.object({\n name: z.string(),\n label: z.string(),\n description: z.string().nullable(),\n sensitive: z.boolean(),\n required: z.boolean(),\n }),\n ),\n teamApp: z.boolean(),\n member: z\n .object({\n userId: z.string(),\n email: z.string().nullable(),\n isCaller: z.boolean(),\n })\n .nullable(),\n memberProblem: z.string().nullable(),\n connected: z.boolean(),\n connectedAt: z.string().nullable(),\n connectUrl: z.string(),\n /**\n * Whether the team's product scopes hide the product from it in the app.\n * Absent from an older host.\n */\n productScope: z\n .object({\n state: z.enum(['unscoped', 'scoped', 'locked_out']),\n scopes: z.array(z.string()),\n hidden: z.boolean(),\n })\n .optional(),\n});\nexport type TeamConnectPlan = z.infer<typeof TeamConnectPlanSchema>;\n\nconst ShowSchema = z.object({ plan: TeamConnectPlanSchema });\nconst StartSchema = z.discriminatedUnion('result', [\n z.object({ plan: TeamConnectPlanSchema, result: z.literal('activated') }),\n z.object({\n plan: TeamConnectPlanSchema,\n result: z.literal('consent'),\n authorizeUrl: z.string(),\n expiresAt: z.string(),\n }),\n]);\nexport type TeamConnectStart = z.infer<typeof StartSchema>;\n\ninterface Target {\n source: string;\n team: string;\n product: string;\n /** A named OAuth connection (`agent`); the main one when absent. */\n connection?: string;\n}\n\nfunction connectPath(target: Target): string {\n return `/api/partner/teams/${encodeURIComponent(target.team)}/integrations/${encodeURIComponent(target.product)}/connect`;\n}\n\nexport function showTeamConnect(\n host: string,\n accessToken: string,\n target: Target,\n asEmail?: string,\n): Promise<TeamsApiResult<z.infer<typeof ShowSchema>>> {\n // `call` puts `source` in the query; the rest ride in the path's own query.\n const query = new URLSearchParams({\n ...(asEmail ? { as: asEmail } : {}),\n ...(target.connection ? { connection: target.connection } : {}),\n }).toString();\n const path = query ? `${connectPath(target)}?${query}` : connectPath(target);\n return call(host, accessToken, ShowSchema, {\n method: 'GET',\n path,\n source: target.source,\n });\n}\n\nexport function startTeamConnect(\n host: string,\n accessToken: string,\n target: Target,\n body: { as?: string; fields?: Record<string, string> },\n): Promise<TeamsApiResult<TeamConnectStart>> {\n return call(host, accessToken, StartSchema, {\n method: 'POST',\n path: connectPath(target),\n source: target.source,\n body: target.connection ? { ...body, connection: target.connection } : body,\n });\n}\n"]}
|
package/dist/teams-api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type TeamAppSetResult, type TeamCreateRequest, type TeamCreateResult, type TeamMemberChangeResult, type TeamMemberInviteResult, type TeamMemberList, type TeamRoles, type TeamIntegrationStatus, type TeamList, type TeamWebhookMintResult } from '@ekanos/integration-schema';
|
|
1
|
+
import { type ProductScopeList, type ProductScopeProductChange, type TeamScopes, type TeamScopesSetResult, type TeamAppSetResult, type TeamCreateRequest, type TeamCreateResult, type TeamDisconnectResult, type TeamMemberChangeResult, type TeamMemberInviteResult, type TeamMemberList, type TeamRenameResult, type TeamRoles, type TeamIntegrationStatus, type TeamIntegrationEventList, type TeamList, type TeamWebhookMintResult } from '@ekanos/integration-schema';
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
/**
|
|
4
4
|
* The CLI's client for a Source's teams and their integration setup — the
|
|
@@ -9,12 +9,21 @@ import type { z } from 'zod';
|
|
|
9
9
|
* PUT …/integrations/<product>/app?source=<slug> { connectionId?, fields }
|
|
10
10
|
* → TeamAppSetResult
|
|
11
11
|
* POST …/integrations/<product>/webhooks/<id>?source=<slug> → TeamWebhookMintResult
|
|
12
|
+
* DELETE /api/partner/teams/<team>/integrations/<product>?source=<slug> → TeamDisconnectResult
|
|
12
13
|
* POST /api/partner/teams?source=<slug> { name, slug?, ownerEmail? } → TeamCreateResult
|
|
14
|
+
* PATCH /api/partner/teams/<team>?source=<slug> { name } → TeamRenameResult
|
|
13
15
|
* GET /api/partner/teams/<team>/members?source=<slug> → TeamMemberList
|
|
14
16
|
* POST …/<team>/members?source=<slug> { email, role } → TeamMemberInviteResult
|
|
15
17
|
* PATCH …/<team>/members/<email>?source=<slug> { role } → TeamMemberChangeResult
|
|
16
18
|
* DELETE …/<team>/members/<email>?source=<slug> → TeamMemberChangeResult
|
|
17
19
|
* GET /api/partner/teams/<team>/roles?source=<slug> → TeamRoles
|
|
20
|
+
* GET /api/partner/teams/<team>/events?source=<slug>[&product=<slug>]
|
|
21
|
+
* [&since=<iso>][&limit=<n>] → TeamIntegrationEventList
|
|
22
|
+
* GET /api/partner/scopes?source=<slug> → ProductScopeList
|
|
23
|
+
* PUT | DELETE /api/partner/scopes/<scope>/products/<product>?source=<slug>
|
|
24
|
+
* → ProductScopeProductChange
|
|
25
|
+
* GET /api/partner/teams/<team>/scopes?source=<slug> → TeamScopes
|
|
26
|
+
* PUT /api/partner/teams/<team>/scopes?source=<slug> { scopes } → TeamScopesSetResult
|
|
18
27
|
*
|
|
19
28
|
* → 401 / 3xx refresh once and retry
|
|
20
29
|
* → 403 { code: "SOURCE_ADMIN_REQUIRED" | "MFA_REQUIRED" | "FORBIDDEN" }
|
|
@@ -51,7 +60,16 @@ export declare function mintTeamWebhook(host: string, accessToken: string, targe
|
|
|
51
60
|
team: string;
|
|
52
61
|
product: string;
|
|
53
62
|
}, webhookId: string): Promise<TeamsApiResult<TeamWebhookMintResult>>;
|
|
63
|
+
export declare function disconnectTeamIntegration(host: string, accessToken: string, target: {
|
|
64
|
+
source: string;
|
|
65
|
+
team: string;
|
|
66
|
+
product: string;
|
|
67
|
+
}): Promise<TeamsApiResult<TeamDisconnectResult>>;
|
|
54
68
|
export declare function createTeam(host: string, accessToken: string, source: string, body: TeamCreateRequest): Promise<TeamsApiResult<TeamCreateResult>>;
|
|
69
|
+
export declare function renameTeam(host: string, accessToken: string, target: {
|
|
70
|
+
source: string;
|
|
71
|
+
team: string;
|
|
72
|
+
}, name: string): Promise<TeamsApiResult<TeamRenameResult>>;
|
|
55
73
|
export declare function listTeamMembers(host: string, accessToken: string, target: {
|
|
56
74
|
source: string;
|
|
57
75
|
team: string;
|
|
@@ -73,10 +91,32 @@ export declare function removeTeamMember(host: string, accessToken: string, targ
|
|
|
73
91
|
team: string;
|
|
74
92
|
email: string;
|
|
75
93
|
}): Promise<TeamsApiResult<TeamMemberChangeResult>>;
|
|
94
|
+
export declare function listProductScopes(host: string, accessToken: string, source: string): Promise<TeamsApiResult<ProductScopeList>>;
|
|
95
|
+
export declare function setScopeProduct(host: string, accessToken: string, target: {
|
|
96
|
+
source: string;
|
|
97
|
+
scope: string;
|
|
98
|
+
product: string;
|
|
99
|
+
}, included: boolean): Promise<TeamsApiResult<ProductScopeProductChange>>;
|
|
100
|
+
export declare function showTeamScopes(host: string, accessToken: string, target: {
|
|
101
|
+
source: string;
|
|
102
|
+
team: string;
|
|
103
|
+
}): Promise<TeamsApiResult<TeamScopes>>;
|
|
104
|
+
export declare function setTeamScopes(host: string, accessToken: string, target: {
|
|
105
|
+
source: string;
|
|
106
|
+
team: string;
|
|
107
|
+
}, scopes: string[]): Promise<TeamsApiResult<TeamScopesSetResult>>;
|
|
76
108
|
export declare function listTeamRoles(host: string, accessToken: string, target: {
|
|
77
109
|
source: string;
|
|
78
110
|
team: string;
|
|
79
111
|
}): Promise<TeamsApiResult<TeamRoles>>;
|
|
112
|
+
export declare function listTeamEvents(host: string, accessToken: string, target: {
|
|
113
|
+
source: string;
|
|
114
|
+
team: string;
|
|
115
|
+
}, filters: {
|
|
116
|
+
product?: string;
|
|
117
|
+
since?: string;
|
|
118
|
+
limit?: number;
|
|
119
|
+
}): Promise<TeamsApiResult<TeamIntegrationEventList>>;
|
|
80
120
|
/** One partner teams call; shared by the team-agent clients (`team-agents-api.ts`). */
|
|
81
121
|
export declare function call<T>(host: string, accessToken: string, schema: z.ZodType<T>, init: {
|
|
82
122
|
method: 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE';
|
package/dist/teams-api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TeamAppSetResultSchema, TeamCreateResultSchema, TeamMemberChangeResultSchema, TeamMemberInviteResultSchema, TeamMemberListSchema, TeamRolesSchema, TeamIntegrationStatusSchema, TeamListSchema, TeamWebhookMintResultSchema, } from '@ekanos/integration-schema';
|
|
1
|
+
import { ProductScopeListSchema, ProductScopeProductChangeSchema, TeamScopesSchema, TeamScopesSetResultSchema, TeamAppSetResultSchema, TeamCreateResultSchema, TeamDisconnectResultSchema, TeamMemberChangeResultSchema, TeamMemberInviteResultSchema, TeamMemberListSchema, TeamRenameResultSchema, TeamRolesSchema, TeamIntegrationStatusSchema, TeamIntegrationEventListSchema, TeamListSchema, TeamWebhookMintResultSchema, } from '@ekanos/integration-schema';
|
|
2
2
|
import { request } from './auth/ekanos-api.js';
|
|
3
3
|
import { authRequiredError, forbiddenError, invalidStateError, networkError, notFoundError, usageError, validationError, } from './errors.js';
|
|
4
4
|
export function listTeams(host, accessToken, source) {
|
|
@@ -30,6 +30,13 @@ export function mintTeamWebhook(host, accessToken, target, webhookId) {
|
|
|
30
30
|
source: target.source,
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
export function disconnectTeamIntegration(host, accessToken, target) {
|
|
34
|
+
return call(host, accessToken, TeamDisconnectResultSchema, {
|
|
35
|
+
method: 'DELETE',
|
|
36
|
+
path: integrationPath(target),
|
|
37
|
+
source: target.source,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
33
40
|
export function createTeam(host, accessToken, source, body) {
|
|
34
41
|
return call(host, accessToken, TeamCreateResultSchema, {
|
|
35
42
|
method: 'POST',
|
|
@@ -38,6 +45,14 @@ export function createTeam(host, accessToken, source, body) {
|
|
|
38
45
|
body,
|
|
39
46
|
});
|
|
40
47
|
}
|
|
48
|
+
export function renameTeam(host, accessToken, target, name) {
|
|
49
|
+
return call(host, accessToken, TeamRenameResultSchema, {
|
|
50
|
+
method: 'PATCH',
|
|
51
|
+
path: `/api/partner/teams/${encodeURIComponent(target.team)}`,
|
|
52
|
+
source: target.source,
|
|
53
|
+
body: { name },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
41
56
|
export function listTeamMembers(host, accessToken, target) {
|
|
42
57
|
return call(host, accessToken, TeamMemberListSchema, {
|
|
43
58
|
method: 'GET',
|
|
@@ -68,6 +83,35 @@ export function removeTeamMember(host, accessToken, target) {
|
|
|
68
83
|
source: target.source,
|
|
69
84
|
});
|
|
70
85
|
}
|
|
86
|
+
export function listProductScopes(host, accessToken, source) {
|
|
87
|
+
return call(host, accessToken, ProductScopeListSchema, {
|
|
88
|
+
method: 'GET',
|
|
89
|
+
path: '/api/partner/scopes',
|
|
90
|
+
source,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export function setScopeProduct(host, accessToken, target, included) {
|
|
94
|
+
return call(host, accessToken, ProductScopeProductChangeSchema, {
|
|
95
|
+
method: included ? 'PUT' : 'DELETE',
|
|
96
|
+
path: `/api/partner/scopes/${encodeURIComponent(target.scope)}/products/${encodeURIComponent(target.product)}`,
|
|
97
|
+
source: target.source,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export function showTeamScopes(host, accessToken, target) {
|
|
101
|
+
return call(host, accessToken, TeamScopesSchema, {
|
|
102
|
+
method: 'GET',
|
|
103
|
+
path: `/api/partner/teams/${encodeURIComponent(target.team)}/scopes`,
|
|
104
|
+
source: target.source,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
export function setTeamScopes(host, accessToken, target, scopes) {
|
|
108
|
+
return call(host, accessToken, TeamScopesSetResultSchema, {
|
|
109
|
+
method: 'PUT',
|
|
110
|
+
path: `/api/partner/teams/${encodeURIComponent(target.team)}/scopes`,
|
|
111
|
+
source: target.source,
|
|
112
|
+
body: { scopes },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
71
115
|
export function listTeamRoles(host, accessToken, target) {
|
|
72
116
|
return call(host, accessToken, TeamRolesSchema, {
|
|
73
117
|
method: 'GET',
|
|
@@ -75,6 +119,22 @@ export function listTeamRoles(host, accessToken, target) {
|
|
|
75
119
|
source: target.source,
|
|
76
120
|
});
|
|
77
121
|
}
|
|
122
|
+
export function listTeamEvents(host, accessToken, target, filters) {
|
|
123
|
+
const query = new URLSearchParams();
|
|
124
|
+
if (filters.product)
|
|
125
|
+
query.set('product', filters.product);
|
|
126
|
+
if (filters.since)
|
|
127
|
+
query.set('since', filters.since);
|
|
128
|
+
if (filters.limit !== undefined)
|
|
129
|
+
query.set('limit', String(filters.limit));
|
|
130
|
+
const encoded = query.toString();
|
|
131
|
+
const suffix = encoded ? `?${encoded}` : '';
|
|
132
|
+
return call(host, accessToken, TeamIntegrationEventListSchema, {
|
|
133
|
+
method: 'GET',
|
|
134
|
+
path: `/api/partner/teams/${encodeURIComponent(target.team)}/events${suffix}`,
|
|
135
|
+
source: target.source,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
78
138
|
function membersPath(team) {
|
|
79
139
|
return `/api/partner/teams/${encodeURIComponent(team)}/members`;
|
|
80
140
|
}
|
|
@@ -103,22 +163,28 @@ export async function call(host, accessToken, schema, init) {
|
|
|
103
163
|
if (response.status === 403) {
|
|
104
164
|
throw forbiddenError(message !== null && message !== void 0 ? message : 'Not permitted on this Source.', code === 'SOURCE_ADMIN_REQUIRED'
|
|
105
165
|
? "Only a Source admin manages its teams' integrations. Ask one to run it."
|
|
106
|
-
:
|
|
166
|
+
: code === 'CONFIRM_NOT_PERMITTED'
|
|
167
|
+
? "Only a Source admin of the team's Source, or someone who manages the team's agents, confirms what an agent may use."
|
|
168
|
+
: 'Run "ekanos sources" to list the sources you hold a seat on.');
|
|
107
169
|
}
|
|
108
170
|
if (response.status === 404) {
|
|
109
171
|
throw notFoundError(message !== null && message !== void 0 ? message : 'Not found.', code === 'TEAM_NOT_FOUND'
|
|
110
172
|
? 'Run "ekanos teams list" to see the teams on this Source.'
|
|
111
173
|
: code === 'PRODUCT_NOT_ENTITLED'
|
|
112
|
-
? '"ekanos
|
|
113
|
-
: code === '
|
|
114
|
-
? 'Run "ekanos
|
|
115
|
-
: code === '
|
|
116
|
-
? 'Run "ekanos teams
|
|
117
|
-
:
|
|
118
|
-
? 'Run "ekanos teams
|
|
119
|
-
:
|
|
120
|
-
? '
|
|
121
|
-
:
|
|
174
|
+
? '"ekanos sources products" shows what this Source has; only a super-admin enables a product for a Source (in /admin).'
|
|
175
|
+
: code === 'SCOPE_NOT_FOUND' || code === 'PRODUCT_NOT_IN_SCOPE'
|
|
176
|
+
? 'Run "ekanos sources scopes" to see the Source\'s product scopes and their products.'
|
|
177
|
+
: code === 'WEBHOOK_NOT_FOUND' || code === 'CONNECTION_NOT_FOUND'
|
|
178
|
+
? 'Run "ekanos teams show <team> <product>" to see its team apps and webhooks.'
|
|
179
|
+
: code === 'MEMBER_NOT_FOUND'
|
|
180
|
+
? 'Run "ekanos teams members list <team>" to see its members and invitations.'
|
|
181
|
+
: code === 'SKILL_NOT_FOUND'
|
|
182
|
+
? 'Run "ekanos skills list --team <team>" (and "ekanos skills list") to see the skills this team can use.'
|
|
183
|
+
: (code === null || code === void 0 ? void 0 : code.startsWith('AGENT_')) || code === 'TEMPLATE_NOT_FOUND'
|
|
184
|
+
? 'Run "ekanos teams agents list <team>" to see the team\'s agents.'
|
|
185
|
+
: /^(TRIGGER|LINK|MCP)_/.test(code !== null && code !== void 0 ? code : '')
|
|
186
|
+
? 'List them first: "ekanos teams triggers|links|mcp list <team> ..."'
|
|
187
|
+
: 'Run "ekanos sources" to list the sources you hold a seat on.');
|
|
122
188
|
}
|
|
123
189
|
if (response.status === 409 && code === 'NO_TEAM_APP') {
|
|
124
190
|
throw invalidStateError(message !== null && message !== void 0 ? message : 'This integration takes no team app.', 'Teams connect through the Source\'s app: "ekanos apps show <product>".');
|
|
@@ -126,13 +192,23 @@ export async function call(host, accessToken, schema, init) {
|
|
|
126
192
|
if (response.status === 409 || response.status === 422) {
|
|
127
193
|
throw invalidStateError(message !== null && message !== void 0 ? message : 'The host refused the change.', code === 'SLUG_TAKEN'
|
|
128
194
|
? 'Pick another with --slug, or run "ekanos teams list" to see the teams.'
|
|
129
|
-
: code === '
|
|
130
|
-
? '
|
|
131
|
-
: code === '
|
|
132
|
-
? "
|
|
133
|
-
: code === '
|
|
134
|
-
? '
|
|
135
|
-
:
|
|
195
|
+
: code === 'AGENT_VERSION_CHANGED'
|
|
196
|
+
? 'A newer version was published since it was shown to you. Review it with "ekanos teams agents show <team> <key>", then run "ekanos teams agents confirm" again.'
|
|
197
|
+
: code === 'ALREADY_MEMBER' || code === 'ALREADY_INVITED'
|
|
198
|
+
? 'Run "ekanos teams members list <team>"; change a role with "ekanos teams members role <team> <email> <role>".'
|
|
199
|
+
: code === 'PRIMARY_OWNER'
|
|
200
|
+
? "The primary owner's ownership is transferred in the app (team Settings → Members)."
|
|
201
|
+
: code === 'TEAM_ACCOUNTS_DISABLED'
|
|
202
|
+
? 'Ekanos switches team accounts on for a Source; ask a super-admin.'
|
|
203
|
+
: code === 'PERSONAL_CONNECTION'
|
|
204
|
+
? "The member who made it disconnects it on the team's Integrations page in the app."
|
|
205
|
+
: code === 'MCP_SERVER_FROM_TEMPLATE'
|
|
206
|
+
? 'It stays while the agent template declares it: change the template, apply and publish.'
|
|
207
|
+
: code === 'PRODUCT_NOT_ENTITLED'
|
|
208
|
+
? '"ekanos sources products" shows what this Source has; only those can be in its scopes.'
|
|
209
|
+
: code === 'TEMPLATE_ARCHIVED'
|
|
210
|
+
? 'Unarchive it first: "ekanos agents unarchive <key>".'
|
|
211
|
+
: 'See "ekanos teams --help".');
|
|
136
212
|
}
|
|
137
213
|
if (response.status === 400 && code === 'UNKNOWN_ROLE') {
|
|
138
214
|
throw validationError(message !== null && message !== void 0 ? message : 'No such role.', 'Run "ekanos teams roles list <team>" for the roles this Source uses.');
|