typeclaw 0.36.4 → 0.36.5
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/package.json +2 -2
- package/src/config/config.ts +20 -0
- package/src/config/index.ts +4 -0
- package/src/container/start.ts +2 -2
- package/src/init/index.ts +14 -2
- package/src/init/line-auth.ts +49 -4
- package/src/run/index.ts +9 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typeclaw",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.5",
|
|
4
4
|
"homepage": "https://github.com/typeclaw/typeclaw#readme",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/typeclaw/typeclaw/issues"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@mariozechner/pi-tui": "^0.67.3",
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
50
50
|
"@mozilla/readability": "^0.6.0",
|
|
51
|
-
"agent-messenger": "2.19.
|
|
51
|
+
"agent-messenger": "2.19.5",
|
|
52
52
|
"cheerio": "^1.2.0",
|
|
53
53
|
"citty": "^0.2.2",
|
|
54
54
|
"cron-parser": "^5.5.0",
|
package/src/config/config.ts
CHANGED
|
@@ -25,6 +25,26 @@ const knownModelRefs = listKnownModelRefs() as [KnownModelRef, ...KnownModelRef[
|
|
|
25
25
|
// T9 keypad: T=8, Y=9, P=7, E=3
|
|
26
26
|
const DEFAULT_PORT = 8973
|
|
27
27
|
|
|
28
|
+
export const GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE = 'typeclaw-gws-multi-account'
|
|
29
|
+
export const GWS_MULTI_ACCOUNT_PLUGIN_VERSION = '^0.3.4'
|
|
30
|
+
export const DEFAULT_PLUGINS = [`${GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE}@${GWS_MULTI_ACCOUNT_PLUGIN_VERSION}`] as const
|
|
31
|
+
|
|
32
|
+
export function withDefaultPlugins(plugins: readonly string[]): string[] {
|
|
33
|
+
const configuredNames = new Set(plugins.map(pluginPackageName))
|
|
34
|
+
const defaults = DEFAULT_PLUGINS.filter((entry) => !configuredNames.has(pluginPackageName(entry)))
|
|
35
|
+
return [...defaults, ...plugins]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function pluginPackageName(entry: string): string {
|
|
39
|
+
if (entry.startsWith('@')) {
|
|
40
|
+
const slash = entry.indexOf('/')
|
|
41
|
+
const at = slash === -1 ? -1 : entry.indexOf('@', slash + 1)
|
|
42
|
+
return at === -1 ? entry : entry.slice(0, at)
|
|
43
|
+
}
|
|
44
|
+
const at = entry.indexOf('@')
|
|
45
|
+
return at === -1 ? entry : entry.slice(0, at)
|
|
46
|
+
}
|
|
47
|
+
|
|
28
48
|
// Mount names land on disk as `mounts/<name>` inside the agent folder, so they
|
|
29
49
|
// share a namespace with regular filenames. Restricting to lowercase
|
|
30
50
|
// alphanumerics + `-`/`_` keeps them shell-safe and avoids accidental shadowing
|
package/src/config/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export {
|
|
|
2
2
|
buildConfigMigrationCommitMessage,
|
|
3
3
|
config,
|
|
4
4
|
configSchema,
|
|
5
|
+
DEFAULT_PLUGINS,
|
|
5
6
|
dockerSchema,
|
|
6
7
|
dockerfileSchema,
|
|
7
8
|
expandMountPath,
|
|
@@ -9,6 +10,8 @@ export {
|
|
|
9
10
|
getConfig,
|
|
10
11
|
gitSchema,
|
|
11
12
|
gitignoreSchema,
|
|
13
|
+
GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE,
|
|
14
|
+
GWS_MULTI_ACCOUNT_PLUGIN_VERSION,
|
|
12
15
|
loadConfigSync,
|
|
13
16
|
loadConfigSyncOrDefaults,
|
|
14
17
|
loadPluginConfigsSync,
|
|
@@ -22,6 +25,7 @@ export {
|
|
|
22
25
|
resolveProfile,
|
|
23
26
|
validateConfig,
|
|
24
27
|
validateMount,
|
|
28
|
+
withDefaultPlugins,
|
|
25
29
|
type Config,
|
|
26
30
|
type ConfigChange,
|
|
27
31
|
type ConfigReloadDiff,
|
package/src/container/start.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync } from 'node:fs'
|
|
|
3
3
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
4
4
|
import { isAbsolute, join, resolve } from 'node:path'
|
|
5
5
|
|
|
6
|
-
import { expandMountPath, loadConfigSync, type Config } from '@/config'
|
|
6
|
+
import { expandMountPath, loadConfigSync, withDefaultPlugins, type Config } from '@/config'
|
|
7
7
|
import { commitGitignoreWithUntracks, untrackTrulyIgnoredFiles } from '@/git/reconcile-ignored'
|
|
8
8
|
import { commitSystemFile as commitSystemFileShared } from '@/git/system-commit'
|
|
9
9
|
import { send as sendToDaemon } from '@/hostd/client'
|
|
@@ -263,7 +263,7 @@ export async function start({
|
|
|
263
263
|
// field is trustworthy by construction.
|
|
264
264
|
const pluginReconcile = await reconcilePluginDeps({
|
|
265
265
|
cwd,
|
|
266
|
-
plugins: (await loadTypeclawConfig(cwd)).plugins,
|
|
266
|
+
plugins: withDefaultPlugins((await loadTypeclawConfig(cwd)).plugins),
|
|
267
267
|
}).catch((error: unknown) => ({ error: error instanceof Error ? error.message : String(error) }) as const)
|
|
268
268
|
if ('error' in pluginReconcile) {
|
|
269
269
|
return { ok: false, reason: `plugin dependency reconcile failed: ${pluginReconcile.error}` }
|
package/src/init/index.ts
CHANGED
|
@@ -3,7 +3,14 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
|
3
3
|
import { basename, dirname, join, relative, resolve } from 'node:path'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
config,
|
|
8
|
+
configSchema,
|
|
9
|
+
GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE,
|
|
10
|
+
GWS_MULTI_ACCOUNT_PLUGIN_VERSION,
|
|
11
|
+
migrateLegacyConfigShape,
|
|
12
|
+
type Config,
|
|
13
|
+
} from '@/config'
|
|
7
14
|
import {
|
|
8
15
|
DEFAULT_MODEL_REF,
|
|
9
16
|
KNOWN_PROVIDERS,
|
|
@@ -577,7 +584,6 @@ export async function scaffold(root: string, options: ScaffoldOptions = {}): Pro
|
|
|
577
584
|
// to function. The Dockerfile pre-downloads Chromium too, so the agent
|
|
578
585
|
// can drive a browser without any first-run setup.
|
|
579
586
|
const AGENT_BROWSER_VERSION = '^0.26.0'
|
|
580
|
-
|
|
581
587
|
function buildPackageJson(root: string, name: string): Record<string, unknown> {
|
|
582
588
|
return {
|
|
583
589
|
name,
|
|
@@ -587,6 +593,12 @@ function buildPackageJson(root: string, name: string): Record<string, unknown> {
|
|
|
587
593
|
dependencies: {
|
|
588
594
|
typeclaw: resolveTypeclawSpec(root),
|
|
589
595
|
'agent-browser': AGENT_BROWSER_VERSION,
|
|
596
|
+
[GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE]: GWS_MULTI_ACCOUNT_PLUGIN_VERSION,
|
|
597
|
+
},
|
|
598
|
+
typeclaw: {
|
|
599
|
+
managedPlugins: {
|
|
600
|
+
[GWS_MULTI_ACCOUNT_PLUGIN_PACKAGE]: GWS_MULTI_ACCOUNT_PLUGIN_VERSION,
|
|
601
|
+
},
|
|
590
602
|
},
|
|
591
603
|
}
|
|
592
604
|
}
|
package/src/init/line-auth.ts
CHANGED
|
@@ -44,6 +44,8 @@ export type LineLoginClient = {
|
|
|
44
44
|
}): Promise<LineLoginResult>
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
let lineTokenInfoSuppressionQueue: Promise<void> = Promise.resolve()
|
|
48
|
+
|
|
47
49
|
export function lineSecretsPath(agentDir: string): string {
|
|
48
50
|
return join(agentDir, 'secrets.json')
|
|
49
51
|
}
|
|
@@ -58,19 +60,20 @@ export async function runLineBootstrap(input: LineLoginInput): Promise<LineBoots
|
|
|
58
60
|
// ~/.config/agent-messenger to keep in sync.
|
|
59
61
|
const client = input.client ?? buildLineClient(store)
|
|
60
62
|
|
|
61
|
-
const result =
|
|
63
|
+
const result = await suppressLineTokenInfoDump(() =>
|
|
62
64
|
input.method === 'qr'
|
|
63
|
-
?
|
|
65
|
+
? client.loginWithQR({
|
|
64
66
|
onQRUrl: async (url) => {
|
|
65
67
|
await input.callbacks.onQRUrl?.(url)
|
|
66
68
|
},
|
|
67
69
|
onPincode: input.callbacks.onPincode,
|
|
68
70
|
})
|
|
69
|
-
:
|
|
71
|
+
: client.loginWithEmail({
|
|
70
72
|
email: input.email,
|
|
71
73
|
password: input.password,
|
|
72
74
|
onPincode: input.callbacks.onPincode,
|
|
73
|
-
})
|
|
75
|
+
}),
|
|
76
|
+
)
|
|
74
77
|
|
|
75
78
|
if (!result.authenticated || result.account_id === undefined) {
|
|
76
79
|
const reason = result.message ?? result.error ?? 'LINE login did not authenticate'
|
|
@@ -101,3 +104,45 @@ function buildLineClient(store: SecretsLineCredentialStore): LineLoginClient {
|
|
|
101
104
|
const credManager = store as unknown as LineCredentialManager
|
|
102
105
|
return new RealLineClient(credManager) as unknown as LineLoginClient
|
|
103
106
|
}
|
|
107
|
+
|
|
108
|
+
async function suppressLineTokenInfoDump<T>(fn: () => Promise<T>): Promise<T> {
|
|
109
|
+
const previous = lineTokenInfoSuppressionQueue
|
|
110
|
+
let release: () => void = () => {}
|
|
111
|
+
lineTokenInfoSuppressionQueue = new Promise((resolve) => {
|
|
112
|
+
release = resolve
|
|
113
|
+
})
|
|
114
|
+
await previous
|
|
115
|
+
|
|
116
|
+
const originalLog = console.log
|
|
117
|
+
console.log = (...args: unknown[]) => {
|
|
118
|
+
if (isLineTokenInfoDump(args)) return
|
|
119
|
+
originalLog(...args)
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
return await fn()
|
|
123
|
+
} finally {
|
|
124
|
+
console.log = originalLog
|
|
125
|
+
release()
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isLineTokenInfoDump(args: unknown[]): boolean {
|
|
130
|
+
if (args.length !== 1) return false
|
|
131
|
+
const value = args[0]
|
|
132
|
+
if (value === null || typeof value !== 'object') return false
|
|
133
|
+
|
|
134
|
+
const record = value as Record<string, unknown>
|
|
135
|
+
return (
|
|
136
|
+
looksLikeJwt(record['1']) &&
|
|
137
|
+
looksLikeJwt(record['2']) &&
|
|
138
|
+
typeof record['3'] === 'number' &&
|
|
139
|
+
typeof record['4'] === 'object' &&
|
|
140
|
+
typeof record['5'] === 'string' &&
|
|
141
|
+
typeof record['6'] === 'number'
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function looksLikeJwt(value: unknown): boolean {
|
|
146
|
+
if (typeof value !== 'string') return false
|
|
147
|
+
return /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value)
|
|
148
|
+
}
|
package/src/run/index.ts
CHANGED
|
@@ -28,7 +28,14 @@ import {
|
|
|
28
28
|
type SubagentCompletionBridge,
|
|
29
29
|
} from '@/channels'
|
|
30
30
|
import { createTunnelBridge, type TunnelBridge } from '@/channels/tunnel-bridge'
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
createConfigReloadable,
|
|
33
|
+
getConfig,
|
|
34
|
+
loadConfigSync,
|
|
35
|
+
loadPluginConfigsSync,
|
|
36
|
+
reloadConfig,
|
|
37
|
+
withDefaultPlugins,
|
|
38
|
+
} from '@/config'
|
|
32
39
|
import {
|
|
33
40
|
type CountStore,
|
|
34
41
|
type CronConsumer,
|
|
@@ -162,7 +169,7 @@ export async function startAgent({
|
|
|
162
169
|
}
|
|
163
170
|
const mcpManagerOpt = mcpManager !== null ? { mcpManager } : {}
|
|
164
171
|
const pluginsLoaded = await loadPlugins({
|
|
165
|
-
entries: cwdConfig.plugins,
|
|
172
|
+
entries: withDefaultPlugins(cwdConfig.plugins),
|
|
166
173
|
agentDir: cwd,
|
|
167
174
|
configsByName: pluginConfigsByName,
|
|
168
175
|
bundled: BUNDLED_PLUGINS,
|