@kin-tio/cli 0.6.2 → 0.7.1
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/.env.example +4 -2
- package/CHANGELOG.md +34 -0
- package/README.md +53 -15
- package/README.zh-CN.md +34 -9
- package/bin/kintio.js +11 -1
- package/dist/daemon.js +5 -0
- package/dist/ilink.js +53 -0
- package/dist/src/cli.js +330 -13
- package/dist/src/config.js +72 -17
- package/dist/src/ilink/cli-accounts.js +74 -0
- package/dist/src/ilink/cli-login.js +563 -0
- package/dist/src/ilink/cli-start.js +60 -0
- package/dist/src/ilink/enrollment.js +24 -0
- package/dist/src/ilink/login-manager.js +102 -30
- package/dist/src/ilink/login-store.js +78 -29
- package/dist/src/ilink/qr.js +67 -3
- package/dist/src/ilink/secret-box.js +73 -0
- package/dist/src/ilink/sqlite-store.js +211 -13
- package/dist/src/mcp/ilink-login-server.js +160 -0
- package/dist/src/mcp/ipc-host.js +4 -1
- package/dist/src/mcp/ipc-protocol.js +22 -0
- package/dist/src/runtime/daemon-protocol.js +1 -0
- package/dist/src/runtime/native-daemon.js +11 -3
- package/dist/src/runtime.js +228 -92
- package/dist/src/services/codex-agent.js +57 -27
- package/dist/src/services/codex-app-server.js +17 -6
- package/dist/src/services/conversation-processor.js +8 -2
- package/dist/src/state/sqlite-store.js +151 -10
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
package/.env.example
CHANGED
|
@@ -28,8 +28,10 @@ WECOM_AUTH_CONFIRMATION=Code accepted. You can continue the conversation.
|
|
|
28
28
|
# WECOM_MCP_OBSERVE_MS=5000
|
|
29
29
|
# SHUTDOWN_TIMEOUT_MS=10000
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
#
|
|
31
|
+
# Enable Weixin iLink inside the combined `kintio start` runtime. Standalone
|
|
32
|
+
# `kintio ilink login` and `kintio ilink start` do not require this flag.
|
|
33
|
+
# Generate a 32-byte base64url key and keep it in the deployment secret store;
|
|
34
|
+
# Bot and context tokens are encrypted with it.
|
|
33
35
|
ILINK_ENABLED=false
|
|
34
36
|
# Prefer a deployment-secret value. If omitted, the service creates a private
|
|
35
37
|
# 0600 key file beside SQLite; never register that key with a chat Agent.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,40 @@ This file records important user-visible changes after the first public release.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.7.1
|
|
8
|
+
|
|
9
|
+
- Made `kintio ilink start` use the managed background daemon by default while
|
|
10
|
+
retaining `--foreground` for external service managers, simplified
|
|
11
|
+
`kintio ilink list` to reusable provider account IDs, rejected Node.js below
|
|
12
|
+
24 before application startup, and added sanitized Codex request diagnostics
|
|
13
|
+
([#65](https://github.com/Gkxie/kintio/issues/65)).
|
|
14
|
+
|
|
15
|
+
## 0.7.0
|
|
16
|
+
|
|
17
|
+
- Added `kintio ilink login`, which reuses the iLink enrollment state machine
|
|
18
|
+
while rendering its five-minute QR code directly in an interactive terminal;
|
|
19
|
+
no WeChat KF conversation or Agent turn is required. Accounts
|
|
20
|
+
enrolled locally receive host-level Agent access and inherit the host runtime
|
|
21
|
+
configuration, while remotely offered iLink accounts remain restricted
|
|
22
|
+
([#54](https://github.com/Gkxie/kintio/issues/54)).
|
|
23
|
+
- Added an explicit `--qr-output <file>` view for `kintio ilink login`, allowing
|
|
24
|
+
graphical and non-terminal callers to consume a temporary raw PNG directly
|
|
25
|
+
from the QR payload without parsing ANSI terminal output. The file is created
|
|
26
|
+
exclusively and removed when the login attempt ends
|
|
27
|
+
([#57](https://github.com/Gkxie/kintio/issues/57)).
|
|
28
|
+
- Made iLink a standalone lifecycle: `kintio ilink login` now initializes and
|
|
29
|
+
persists an account without setup, an environment file, Hono, or a running
|
|
30
|
+
Worker, while safely delegating to a running instance when present;
|
|
31
|
+
`kintio ilink start` starts polling and the host Agent in the foreground without
|
|
32
|
+
a public HTTP listener. The iLink Runtime configuration no longer contains a
|
|
33
|
+
synthetic WeChat KF adapter
|
|
34
|
+
([#59](https://github.com/Gkxie/kintio/issues/59)).
|
|
35
|
+
- Added per-account `kintio ilink list`, `start`, `stop`, and confirmed `delete`
|
|
36
|
+
lifecycle commands. One Runtime can reconcile multiple selected listeners;
|
|
37
|
+
complete deletion atomically purges the selected account and all Kintio data
|
|
38
|
+
scoped to it while preserving unrelated accounts and channels
|
|
39
|
+
([#60](https://github.com/Gkxie/kintio/issues/60)).
|
|
40
|
+
|
|
7
41
|
## 0.6.2
|
|
8
42
|
|
|
9
43
|
- Added a custom Kintio wordmark and its circular-safe TIO avatar to the English
|
package/README.md
CHANGED
|
@@ -67,33 +67,68 @@ Prerequisites:
|
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
69
|
npm install --global @kin-tio/cli
|
|
70
|
-
kintio setup
|
|
71
70
|
codex login status
|
|
72
71
|
```
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
skill, and writes the channel configuration template. POSIX systems use mode `0600`;
|
|
76
|
-
Windows keeps the instance inside the current user's profile. No adapter is enabled
|
|
77
|
-
by default. Follow the [setup guide](https://github.com/Gkxie/kintio/blob/master/docs/setup.md)
|
|
78
|
-
and edit `~/.kintio/.env` to configure one adapter:
|
|
73
|
+
For an iLink-only instance, no setup file or public HTTP listener is required:
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
currently starts from an authorized WeChat KF conversation.
|
|
75
|
+
```bash
|
|
76
|
+
kintio ilink login
|
|
77
|
+
kintio ilink start
|
|
78
|
+
```
|
|
85
79
|
|
|
86
|
-
|
|
80
|
+
`ilink login` performs one encrypted enrollment, starts no listener, and exits. `ilink start` then runs provider
|
|
81
|
+
polling and the host Agent through the background daemon without Hono or a TCP listener.
|
|
82
|
+
Use `--foreground` only when a service manager needs to own the process. Both commands
|
|
83
|
+
use `~/.kintio` by default and accept `--home`. With multiple accounts, use `ilink list`
|
|
84
|
+
and pass the displayed provider ID or account key through `--account`. Repeated `start`
|
|
85
|
+
commands add accounts to the live runtime; `stop` removes one.
|
|
86
|
+
|
|
87
|
+
For a callback-based adapter, create and edit the deployment configuration instead:
|
|
87
88
|
|
|
88
89
|
```bash
|
|
90
|
+
kintio setup
|
|
89
91
|
kintio start
|
|
90
92
|
kintio status
|
|
91
93
|
kintio logs --lines 100
|
|
92
94
|
```
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
`kintio setup` creates a private instance under `~/.kintio`, installs the managed Agent
|
|
97
|
+
skill, and writes the channel configuration template. Follow the
|
|
98
|
+
[setup guide](https://github.com/Gkxie/kintio/blob/master/docs/setup.md):
|
|
99
|
+
|
|
100
|
+
- For WeChat KF API, set its callback token, EncodingAESKey, CorpID, and secret. A temporary
|
|
101
|
+
`WECOM_AUTH_TRIGGER` can authorize the first user without knowing their
|
|
102
|
+
`external_userid` in advance.
|
|
103
|
+
- A combined callback + iLink deployment may additionally set `ILINK_ENABLED=true`.
|
|
104
|
+
|
|
105
|
+
For a graphical or non-terminal caller, select a temporary raw PNG instead of ANSI blocks:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
kintio ilink login --qr-output ~/.kintio/ilink-login.png
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The target must be directly inside the selected Kintio instance directory and must not
|
|
112
|
+
already exist. Kintio removes the PNG when login succeeds, expires, is cancelled, or fails;
|
|
113
|
+
the QR payload is never printed. Without `--qr-output`, the command
|
|
114
|
+
requires an interactive terminal. Both forms stop waiting after five minutes and never
|
|
115
|
+
start an Agent turn. The resulting iLink identity represents
|
|
116
|
+
the local operator and inherits the host Agent configuration without Kintio's untrusted-
|
|
117
|
+
channel capability restrictions. Show this QR code only to someone authorized to control
|
|
118
|
+
the host Agent. Run `kintio ilink start` after enrollment to process messages without Hono.
|
|
119
|
+
|
|
120
|
+
To permanently remove an account and every Kintio record scoped to it, use:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
kintio ilink delete --account <provider-id-or-account-key> --yes
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The explicit confirmation is mandatory. Credentials, conversations, messages, media,
|
|
127
|
+
delivery records, and enrollment audit rows for that account are deleted atomically.
|
|
128
|
+
|
|
129
|
+
For callback deployments, confirm that `kintio logs` contains
|
|
130
|
+
`Hono server is listening on port 8888`. Use `kintio run` when a foreground process is
|
|
131
|
+
preferable to the native daemon.
|
|
97
132
|
Existing source-based deployments can keep their current state after the one-time
|
|
98
133
|
process-manager migration described in the setup guide.
|
|
99
134
|
|
|
@@ -111,6 +146,9 @@ Source builds and contributor setup are documented in
|
|
|
111
146
|
Hono route; every action still requires a short-lived conversation capability.
|
|
112
147
|
- Project-level Agent capability restrictions are not an operating-system sandbox. Use a
|
|
113
148
|
dedicated system account and additional isolation appropriate to the Agent's real powers.
|
|
149
|
+
- An iLink account enrolled by `kintio ilink login` is explicitly host-authorized; its owner
|
|
150
|
+
receives the capabilities allowed by the host Agent configuration. Accounts enrolled from
|
|
151
|
+
a remote adapter remain restricted, and chat input cannot change this persisted trust level.
|
|
114
152
|
- A provider accepting an outbound request does not prove that a client displayed it;
|
|
115
153
|
uncertain outcomes remain explicit to avoid duplicate delivery.
|
|
116
154
|
|
package/README.zh-CN.md
CHANGED
|
@@ -43,25 +43,50 @@
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
npm install --global @kin-tio/cli
|
|
46
|
-
kintio setup
|
|
47
46
|
codex login status
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
`
|
|
51
|
-
模板 `.env`。macOS/Linux 使用 `0600`,Windows 则限定在当前用户目录的 ACL
|
|
52
|
-
边界内。默认不启用任何适配器;请按英文
|
|
53
|
-
[部署指南](https://github.com/Gkxie/kintio/blob/master/docs/setup.md)配置 WeChat KF API,或为已有 Weixin iLink 绑定设置
|
|
54
|
-
`ILINK_ENABLED=true`。
|
|
49
|
+
iLink 可以完全独立使用,不需要 `setup`、`.env` 或公网 HTTP:
|
|
55
50
|
|
|
56
51
|
```bash
|
|
52
|
+
kintio ilink login
|
|
53
|
+
kintio ilink start
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`ilink login` 完成一次扫码、加密保存凭据后退出,不会自行启动监听;`ilink start` 不启动 Hono 或 TCP 端口,
|
|
57
|
+
而是通过后台守护进程运行 iLink 长轮询和宿主 Agent。由外部进程管理器托管时可显式使用
|
|
58
|
+
`--foreground`。两者默认使用 `~/.kintio`。
|
|
59
|
+
存在多个账号时,先用 `kintio ilink list` 查看账号,再通过 `--account` 指定
|
|
60
|
+
`start`、`stop` 或 `delete` 的目标;正在运行时可继续执行 `start` 增加监听账号。
|
|
61
|
+
|
|
62
|
+
需要部署公网回调渠道时,再使用:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
kintio setup
|
|
57
66
|
kintio start
|
|
58
67
|
kintio status
|
|
59
68
|
kintio logs --lines 100
|
|
60
69
|
```
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
具体配置见英文[部署指南](https://github.com/Gkxie/kintio/blob/master/docs/setup.md)。
|
|
72
|
+
|
|
73
|
+
图形界面或非交互调用方可以显式选择临时的原始 PNG,而不是解析终端字符:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
kintio ilink login --qr-output ~/.kintio/ilink-login.png
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
目标文件必须直接位于所选 Kintio 实例目录中且不能预先存在;登录成功、过期、取消或失败后,Kintio 会自动删除该文件,并且
|
|
80
|
+
不会打印二维码原始内容。二维码五分钟后过期;该命令不会唤醒 Agent。通过本机命令建立的 iLink 身份代表宿主机
|
|
81
|
+
所有者的明确授权,后续对话直接继承宿主 Agent 配置,不再套用不可信渠道的能力限制。
|
|
82
|
+
只应让获准控制宿主 Agent 的人扫描该二维码。登录后运行 `kintio ilink start` 即可在不
|
|
83
|
+
启动 Hono 的情况下处理消息。
|
|
84
|
+
|
|
85
|
+
`kintio ilink delete --account <账号> --yes` 会不可恢复地删除该账号及其在 Kintio
|
|
86
|
+
中的凭据、会话、消息、媒体、发送记录和登录审计;`--yes` 为强制确认参数。
|
|
87
|
+
|
|
88
|
+
公网回调部署启动后,应确认 `kintio logs` 包含
|
|
89
|
+
`Hono server is listening on port 8888`。
|
|
65
90
|
源码构建与贡献者开发环境见英文
|
|
66
91
|
[贡献指南](https://github.com/Gkxie/kintio/blob/master/CONTRIBUTING.md)。
|
|
67
92
|
|
package/bin/kintio.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const currentNode = process.versions.node;
|
|
4
|
+
const nodeMajor = Number.parseInt(currentNode.split('.')[0] || '', 10);
|
|
5
|
+
if (!Number.isSafeInteger(nodeMajor) || nodeMajor < 24) {
|
|
6
|
+
process.stderr.write(
|
|
7
|
+
`Kintio requires Node.js 24 or newer; current runtime is v${currentNode}.\n` +
|
|
8
|
+
'Install Node.js 24+, then reinstall @kin-tio/cli in that Node environment.\n',
|
|
9
|
+
);
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
} else {
|
|
12
|
+
await import('../dist/cli.js');
|
|
13
|
+
}
|
package/dist/daemon.js
CHANGED
|
@@ -4,13 +4,18 @@ import { resolveProjectRoot } from './src/config.js';
|
|
|
4
4
|
import { runNativeDaemon } from './src/runtime/native-daemon.js';
|
|
5
5
|
const home = process.env.KINTIO_HOME;
|
|
6
6
|
const configFile = process.env.KINTIO_CONFIG_FILE;
|
|
7
|
+
const mode = process.env.KINTIO_DAEMON_MODE || 'service';
|
|
7
8
|
if (!home || !configFile) {
|
|
8
9
|
throw new Error('KINTIO_HOME and KINTIO_CONFIG_FILE are required for daemon mode');
|
|
9
10
|
}
|
|
11
|
+
if (mode !== 'service' && mode !== 'ilink') {
|
|
12
|
+
throw new Error(`Unsupported Kintio daemon mode: ${mode}`);
|
|
13
|
+
}
|
|
10
14
|
try {
|
|
11
15
|
await runNativeDaemon({
|
|
12
16
|
home: path.resolve(home),
|
|
13
17
|
configFile: path.resolve(configFile),
|
|
18
|
+
mode,
|
|
14
19
|
packageRoot: resolveProjectRoot(import.meta.url),
|
|
15
20
|
});
|
|
16
21
|
}
|
package/dist/ilink.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { KINTIO_PACKAGE_ROOT, loadIlinkRuntimeConfig, } from './src/config.js';
|
|
2
|
+
import { startIlinkCliRuntime } from './src/ilink/cli-start.js';
|
|
3
|
+
import { installManagedSkill } from './src/runtime/managed-skill.js';
|
|
4
|
+
const config = loadIlinkRuntimeConfig();
|
|
5
|
+
installManagedSkill({
|
|
6
|
+
packageRoot: KINTIO_PACKAGE_ROOT,
|
|
7
|
+
workingDirectory: config.codex.workingDirectory,
|
|
8
|
+
});
|
|
9
|
+
const controller = new AbortController();
|
|
10
|
+
let resolveParentShutdown;
|
|
11
|
+
const parentShutdown = new Promise((resolve) => { resolveParentShutdown = resolve; });
|
|
12
|
+
const shutdown = () => {
|
|
13
|
+
controller.abort();
|
|
14
|
+
resolveParentShutdown();
|
|
15
|
+
};
|
|
16
|
+
process.once('SIGINT', shutdown);
|
|
17
|
+
process.once('SIGTERM', shutdown);
|
|
18
|
+
const handleMessage = (message) => {
|
|
19
|
+
if (message === 'shutdown')
|
|
20
|
+
shutdown();
|
|
21
|
+
};
|
|
22
|
+
process.on('message', handleMessage);
|
|
23
|
+
process.once('disconnect', shutdown);
|
|
24
|
+
if (process.env.KINTIO_MANAGED_WORKER === '1' && !process.connected)
|
|
25
|
+
shutdown();
|
|
26
|
+
try {
|
|
27
|
+
const result = await startIlinkCliRuntime({
|
|
28
|
+
background: true,
|
|
29
|
+
config,
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
stdout: (text) => process.stdout.write(text),
|
|
32
|
+
onStarted() {
|
|
33
|
+
process.send?.({ type: 'ready', pid: process.pid });
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
if (result === 0 && process.connected) {
|
|
37
|
+
process.send?.({ type: 'shutdown-request', pid: process.pid });
|
|
38
|
+
await parentShutdown;
|
|
39
|
+
}
|
|
40
|
+
process.exitCode = result === 130 ? 0 : result;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error('[ilink] process failed', error);
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
process.off('SIGINT', shutdown);
|
|
48
|
+
process.off('SIGTERM', shutdown);
|
|
49
|
+
process.off('disconnect', shutdown);
|
|
50
|
+
process.off('message', handleMessage);
|
|
51
|
+
if (process.connected)
|
|
52
|
+
process.disconnect();
|
|
53
|
+
}
|