@acosmi/sdk-ts 1.4.1 → 1.5.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/README.md +99 -5
  3. package/dist/browser/index.mjs +2432 -1891
  4. package/dist/browser/index.mjs.map +1 -1
  5. package/dist/index.mjs +2432 -1891
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/node/adapters/anthropic.cjs +6 -4
  8. package/dist/node/adapters/anthropic.cjs.map +1 -1
  9. package/dist/node/adapters/anthropic.d.cts +1 -1
  10. package/dist/node/adapters/anthropic.d.ts +1 -1
  11. package/dist/node/adapters/anthropic.mjs +6 -4
  12. package/dist/node/adapters/anthropic.mjs.map +1 -1
  13. package/dist/node/adapters/openai.cjs +4 -2
  14. package/dist/node/adapters/openai.cjs.map +1 -1
  15. package/dist/node/adapters/openai.d.cts +2 -64
  16. package/dist/node/adapters/openai.d.ts +2 -64
  17. package/dist/node/adapters/openai.mjs +4 -2
  18. package/dist/node/adapters/openai.mjs.map +1 -1
  19. package/dist/node/index-DEA6LXw6.d.cts +409 -0
  20. package/dist/node/index-DEA6LXw6.d.ts +409 -0
  21. package/dist/node/index.cjs +2438 -1890
  22. package/dist/node/index.cjs.map +1 -1
  23. package/dist/node/index.d.cts +2846 -1225
  24. package/dist/node/index.d.ts +2846 -1225
  25. package/dist/node/index.mjs +2432 -1891
  26. package/dist/node/index.mjs.map +1 -1
  27. package/dist/node/openai-BDodfhsG.d.cts +125 -0
  28. package/dist/node/openai-vfUUgdvL.d.ts +125 -0
  29. package/docs/compliance.md +452 -2
  30. package/examples/agent-runs-stream.ts +118 -0
  31. package/examples/auth-oauth-flow.ts +97 -0
  32. package/examples/core-chat.ts +85 -0
  33. package/package.json +5 -2
  34. package/dist/node/index-CbG9NqE-.d.cts +0 -1027
  35. package/dist/node/index-CbG9NqE-.d.ts +0 -1027
@@ -0,0 +1,97 @@
1
+ // examples/auth-oauth-flow.ts — 手动 OAuth 2.1 PKCE 流程示例(CLI / 自定义流程)。
2
+ //
3
+ // 演示:
4
+ // 1. discover — 拉取 OAuth Authorization Server 元数据 (RFC 8414)
5
+ // 2. register — RFC 7591 动态客户端注册
6
+ // 3. authorize — 本地 loopback PKCE 授权 (Node only),拿 authorization code
7
+ // 4. exchangeCode — 用 code + code_verifier 换 token
8
+ // 5. newTokenSet + TokenStore — 持久化 token,后续复用
9
+ // 6. refreshToken — 用 refresh_token 续期
10
+ //
11
+ // 说明:
12
+ // - 大多数场景直接用 `client.login(appName, scopes)` 即可(内部封装了下面全部步骤)。
13
+ // 本示例演示底层 helper,适用于需要自定义授权流程 / 自管 token 的 CLI。
14
+ // - authorize 仅在 Node 环境可用(需要本地 HTTP 回调 server);浏览器侧应自行实现
15
+ // popup window + redirect handler。
16
+
17
+ import {
18
+ discover,
19
+ register,
20
+ authorize,
21
+ exchangeCode,
22
+ refreshToken,
23
+ newTokenSet,
24
+ tokenSetIsExpired,
25
+ FileTokenStore,
26
+ allScopes,
27
+ } from '@acosmi/sdk-ts';
28
+
29
+ async function main() {
30
+ const serverURL = process.env.ACOSMI_SERVER_URL;
31
+ if (!serverURL) {
32
+ throw new Error('ACOSMI_SERVER_URL is required');
33
+ }
34
+ const scopes = allScopes();
35
+ const store = new FileTokenStore(process.env.ACOSMI_TOKEN_FILE ?? './auth-tokens.json');
36
+
37
+ // 0) 已有持久化 token 且未过期 → 直接复用,跳过整个授权流程。
38
+ const existing = await store.load();
39
+ if (existing && !tokenSetIsExpired(existing)) {
40
+ console.log('[token] reusing valid token from store, scope=', existing.scope);
41
+ return;
42
+ }
43
+
44
+ // 1) discover — OAuth Authorization Server 元数据
45
+ const meta = await discover(serverURL);
46
+ console.log('[discover] issuer=', meta.issuer);
47
+ console.log('[discover] token_endpoint=', meta.token_endpoint);
48
+
49
+ // 2) register — 动态注册一个 client,拿到 client_id
50
+ const reg = await register(meta, 'Auth Flow Example');
51
+ console.log('[register] client_id=', reg.client_id);
52
+
53
+ let tokenSet;
54
+
55
+ // 3) refresh-first:store 里有过期 token 但带 refresh_token → 先尝试静默刷新。
56
+ if (existing && existing.refresh_token) {
57
+ try {
58
+ const refreshed = await refreshToken(meta, existing.client_id, existing.refresh_token);
59
+ tokenSet = newTokenSet(refreshed, existing.client_id, serverURL);
60
+ console.log('[refresh] token refreshed without re-authorizing');
61
+ } catch (e) {
62
+ console.warn('[refresh] failed, falling back to full authorize:',
63
+ e instanceof Error ? e.message : e);
64
+ }
65
+ }
66
+
67
+ // 4) 没有可刷新的 token → 走完整 PKCE 授权。
68
+ if (!tokenSet) {
69
+ const { result, verifier } = await authorize(meta, reg.client_id, scopes, {
70
+ handler: (ev) => {
71
+ if (ev.type === 'auth_url') console.log('[authorize] open in browser:', ev.url);
72
+ if (ev.type === 'error') console.error('[authorize] error:', ev.err_code, ev.error);
73
+ },
74
+ });
75
+ console.log('[authorize] received authorization code');
76
+
77
+ // 5) exchangeCode — code + code_verifier 换 token
78
+ const tokenResp = await exchangeCode(
79
+ meta,
80
+ reg.client_id,
81
+ result.code,
82
+ result.redirectURI,
83
+ verifier,
84
+ );
85
+ tokenSet = newTokenSet(tokenResp, reg.client_id, serverURL);
86
+ console.log('[exchange] access token acquired, scope=', tokenSet.scope);
87
+ }
88
+
89
+ // 6) 持久化 token,供下次启动复用 / Client 直接读取。
90
+ await store.save(tokenSet);
91
+ console.log('[store] token persisted; expires_at=', tokenSet.expires_at);
92
+ }
93
+
94
+ main().catch((err) => {
95
+ console.error('auth oauth flow example failed:', err);
96
+ process.exit(1);
97
+ });
@@ -0,0 +1,85 @@
1
+ // examples/core-chat.ts — Client 基础用法示例(构造 / 配置 / 模型列举 / chat / 流式)。
2
+ //
3
+ // 演示:
4
+ // 1. 构造 Client (serverURL + 可选 FileTokenStore)
5
+ // 2. OAuth 登录 (按业务最小集合申请 scope)
6
+ // 3. 列举托管模型 + 查看配额摘要
7
+ // 4. 同步 chat 调用
8
+ // 5. 流式 chatStreamWithUsage 并聚合 usage / 结算事件
9
+ //
10
+ // 说明:
11
+ // - SDK 自动按 ManagedModel 的 preferredFormat / supportedFormats 选 Anthropic
12
+ // 或 OpenAI adapter,调用方无需关心。
13
+ // - 金额 / 余额字段是 string(避免 JS number 精度损失),不要做浮点运算。
14
+
15
+ import { Client, allScopes, FileTokenStore } from '@acosmi/sdk-ts';
16
+
17
+ async function main() {
18
+ const serverURL = process.env.ACOSMI_SERVER_URL;
19
+ if (!serverURL) {
20
+ throw new Error('ACOSMI_SERVER_URL is required');
21
+ }
22
+
23
+ // 1) 构造 Client。Client.create 会从 store 异步加载已持久化的 token。
24
+ // Node 上不传 store 时默认 ~/.acosmi/tokens.json;这里显式指定一个路径。
25
+ const client = await Client.create({
26
+ serverURL,
27
+ store: new FileTokenStore(process.env.ACOSMI_TOKEN_FILE ?? './core-tokens.json'),
28
+ });
29
+
30
+ // 2) OAuth 登录 — 已有有效 token 时 login 会直接复用,不重复弹浏览器。
31
+ await client.login('Core Chat Example', allScopes());
32
+
33
+ // 3) 列举托管模型 + 配额摘要
34
+ const models = await client.listModels();
35
+ console.log('[models]', models.length, 'available');
36
+ for (const m of models.slice(0, 5)) {
37
+ console.log(' -', m.modelId, `(provider=${m.provider}, enabled=${m.isEnabled})`);
38
+ }
39
+
40
+ const quota = await client.getQuotaSummary();
41
+ console.log('[quota] freeTotalEtu=', quota.freeTotalEtu,
42
+ 'paidTotalEtu=', quota.paidTotalEtu);
43
+
44
+ // 选一个模型:优先 isDefault,否则取第一个启用的。
45
+ const model =
46
+ models.find((m) => m.isDefault && m.isEnabled) ??
47
+ models.find((m) => m.isEnabled);
48
+ if (!model) {
49
+ throw new Error('no enabled model available — 让管理员在网关启用一个模型');
50
+ }
51
+ console.log('[selected model]', model.modelId);
52
+
53
+ // 4) 同步 chat 调用
54
+ const resp = await client.chat(model.modelId, {
55
+ messages: [{ role: 'user', content: '用一句话介绍 TypeScript。' }],
56
+ max_tokens: 256,
57
+ });
58
+ for (const block of resp.content) {
59
+ if (block.type === 'text' && block.text) {
60
+ console.log('[chat text]', block.text);
61
+ }
62
+ }
63
+ console.log('[chat usage] input=', resp.usage.input_tokens,
64
+ 'output=', resp.usage.output_tokens);
65
+
66
+ // 5) 流式调用 — chatStreamWithUsage 把内容 / sources / 结算事件分流为带标签的迭代项。
67
+ const stream = client.chatStreamWithUsage(model.modelId, {
68
+ messages: [{ role: 'user', content: '写一首关于海的两行短诗。' }],
69
+ max_tokens: 512,
70
+ });
71
+ for await (const item of stream) {
72
+ if (item.kind === 'content' && item.event.event === 'content_block_delta') {
73
+ process.stdout.write('.'); // 实际项目里在此解析 delta 输出 token
74
+ } else if (item.kind === 'settle') {
75
+ console.log('\n[settle] totalTokens=', item.event.totalTokens,
76
+ 'tokenRemaining=', item.event.tokenRemaining);
77
+ }
78
+ }
79
+ console.log('\n[stream] done');
80
+ }
81
+
82
+ main().catch((err) => {
83
+ console.error('core chat example failed:', err);
84
+ process.exit(1);
85
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acosmi/sdk-ts",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Acosmi TypeScript SDK:模型网关、Agent Run Gateway 与 Compliance(电子证据、时间章、报告、签署 envelope)统一客户端,支持浏览器 / Node ≥18 / Deno / Bun。",
5
5
  "type": "module",
6
6
  "main": "./dist/node/index.cjs",
@@ -51,7 +51,8 @@
51
51
  "format": "prettier --write \"src/**/*.{ts,json}\"",
52
52
  "typecheck": "tsc --noEmit",
53
53
  "test:pack": "node scripts/smoke-pack.mjs",
54
- "prepublishOnly": "npm run typecheck && npm run lint && npm test && npm run build && npm run test:pack"
54
+ "docs": "typedoc",
55
+ "prepublishOnly": "npm run typecheck && npm run lint && npm test && npm run build && npm run test:pack && npm run docs"
55
56
  },
56
57
  "engines": {
57
58
  "node": ">=18"
@@ -90,6 +91,8 @@
90
91
  "eslint": "^8.57.0",
91
92
  "prettier": "^3.0.0",
92
93
  "tsup": "^8.0.0",
94
+ "typedoc": "^0.28.19",
95
+ "typedoc-plugin-markdown": "^4.11.0",
93
96
  "typescript": "^5.4.0",
94
97
  "vitest": "^1.0.0"
95
98
  }