zerg-ztc 0.1.10 → 0.1.12

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 (151) hide show
  1. package/bin/.gitkeep +0 -0
  2. package/bin/ztc-audio-darwin-arm64 +0 -0
  3. package/dist/App.d.ts.map +1 -1
  4. package/dist/App.js +63 -2
  5. package/dist/App.js.map +1 -1
  6. package/dist/agent/commands/dictation.d.ts +3 -0
  7. package/dist/agent/commands/dictation.d.ts.map +1 -0
  8. package/dist/agent/commands/dictation.js +10 -0
  9. package/dist/agent/commands/dictation.js.map +1 -0
  10. package/dist/agent/commands/index.d.ts.map +1 -1
  11. package/dist/agent/commands/index.js +2 -1
  12. package/dist/agent/commands/index.js.map +1 -1
  13. package/dist/agent/commands/types.d.ts +7 -0
  14. package/dist/agent/commands/types.d.ts.map +1 -1
  15. package/dist/components/InputArea.d.ts +1 -0
  16. package/dist/components/InputArea.d.ts.map +1 -1
  17. package/dist/components/InputArea.js +591 -43
  18. package/dist/components/InputArea.js.map +1 -1
  19. package/dist/components/SingleMessage.d.ts.map +1 -1
  20. package/dist/components/SingleMessage.js +157 -7
  21. package/dist/components/SingleMessage.js.map +1 -1
  22. package/dist/config/types.d.ts +6 -0
  23. package/dist/config/types.d.ts.map +1 -1
  24. package/dist/ui/views/status_bar.js +2 -2
  25. package/dist/ui/views/status_bar.js.map +1 -1
  26. package/dist/utils/dictation.d.ts +46 -0
  27. package/dist/utils/dictation.d.ts.map +1 -0
  28. package/dist/utils/dictation.js +409 -0
  29. package/dist/utils/dictation.js.map +1 -0
  30. package/dist/utils/dictation_native.d.ts +51 -0
  31. package/dist/utils/dictation_native.d.ts.map +1 -0
  32. package/dist/utils/dictation_native.js +236 -0
  33. package/dist/utils/dictation_native.js.map +1 -0
  34. package/dist/utils/path_format.d.ts +20 -0
  35. package/dist/utils/path_format.d.ts.map +1 -0
  36. package/dist/utils/path_format.js +90 -0
  37. package/dist/utils/path_format.js.map +1 -0
  38. package/dist/utils/table.d.ts +38 -0
  39. package/dist/utils/table.d.ts.map +1 -0
  40. package/dist/utils/table.js +133 -0
  41. package/dist/utils/table.js.map +1 -0
  42. package/dist/utils/tool_trace.d.ts +7 -2
  43. package/dist/utils/tool_trace.d.ts.map +1 -1
  44. package/dist/utils/tool_trace.js +156 -51
  45. package/dist/utils/tool_trace.js.map +1 -1
  46. package/package.json +5 -1
  47. package/src/App.tsx +0 -813
  48. package/src/agent/agent.ts +0 -534
  49. package/src/agent/backends/anthropic.ts +0 -86
  50. package/src/agent/backends/gemini.ts +0 -119
  51. package/src/agent/backends/inception.ts +0 -23
  52. package/src/agent/backends/index.ts +0 -17
  53. package/src/agent/backends/openai.ts +0 -23
  54. package/src/agent/backends/openai_compatible.ts +0 -143
  55. package/src/agent/backends/types.ts +0 -83
  56. package/src/agent/commands/clipboard.ts +0 -77
  57. package/src/agent/commands/config.ts +0 -204
  58. package/src/agent/commands/debug.ts +0 -23
  59. package/src/agent/commands/emulation.ts +0 -80
  60. package/src/agent/commands/execution.ts +0 -9
  61. package/src/agent/commands/help.ts +0 -20
  62. package/src/agent/commands/history.ts +0 -13
  63. package/src/agent/commands/index.ts +0 -46
  64. package/src/agent/commands/input_mode.ts +0 -22
  65. package/src/agent/commands/keybindings.ts +0 -40
  66. package/src/agent/commands/model.ts +0 -11
  67. package/src/agent/commands/models.ts +0 -116
  68. package/src/agent/commands/permissions.ts +0 -64
  69. package/src/agent/commands/retry.ts +0 -9
  70. package/src/agent/commands/shell.ts +0 -68
  71. package/src/agent/commands/skills.ts +0 -54
  72. package/src/agent/commands/status.ts +0 -19
  73. package/src/agent/commands/types.ts +0 -80
  74. package/src/agent/commands/update.ts +0 -32
  75. package/src/agent/factory.ts +0 -60
  76. package/src/agent/index.ts +0 -20
  77. package/src/agent/runtime/capabilities.ts +0 -7
  78. package/src/agent/runtime/memory.ts +0 -23
  79. package/src/agent/runtime/policy.ts +0 -48
  80. package/src/agent/runtime/session.ts +0 -18
  81. package/src/agent/runtime/tracing.ts +0 -23
  82. package/src/agent/tools/file.ts +0 -178
  83. package/src/agent/tools/index.ts +0 -52
  84. package/src/agent/tools/screenshot.ts +0 -821
  85. package/src/agent/tools/search.ts +0 -138
  86. package/src/agent/tools/shell.ts +0 -69
  87. package/src/agent/tools/skills.ts +0 -28
  88. package/src/agent/tools/types.ts +0 -14
  89. package/src/agent/tools/zerg.ts +0 -50
  90. package/src/cli.tsx +0 -163
  91. package/src/components/ActivityLine.tsx +0 -23
  92. package/src/components/FullScreen.tsx +0 -79
  93. package/src/components/Header.tsx +0 -27
  94. package/src/components/InputArea.tsx +0 -1096
  95. package/src/components/MessageList.tsx +0 -71
  96. package/src/components/SingleMessage.tsx +0 -59
  97. package/src/components/StatusBar.tsx +0 -55
  98. package/src/components/index.tsx +0 -8
  99. package/src/config/types.ts +0 -12
  100. package/src/config.ts +0 -186
  101. package/src/debug/logger.ts +0 -14
  102. package/src/emulation/README.md +0 -24
  103. package/src/emulation/catalog.ts +0 -82
  104. package/src/emulation/trace_style.ts +0 -8
  105. package/src/emulation/types.ts +0 -7
  106. package/src/skills/index.ts +0 -36
  107. package/src/skills/loader.ts +0 -135
  108. package/src/skills/registry.ts +0 -6
  109. package/src/skills/types.ts +0 -10
  110. package/src/types.ts +0 -84
  111. package/src/ui/README.md +0 -44
  112. package/src/ui/core/factory.ts +0 -9
  113. package/src/ui/core/index.ts +0 -4
  114. package/src/ui/core/input.ts +0 -38
  115. package/src/ui/core/input_segments.ts +0 -410
  116. package/src/ui/core/input_state.ts +0 -17
  117. package/src/ui/core/layout_yoga.ts +0 -122
  118. package/src/ui/core/style.ts +0 -38
  119. package/src/ui/core/types.ts +0 -54
  120. package/src/ui/ink/index.tsx +0 -1
  121. package/src/ui/ink/render.tsx +0 -60
  122. package/src/ui/views/activity_line.ts +0 -33
  123. package/src/ui/views/app.ts +0 -111
  124. package/src/ui/views/header.ts +0 -44
  125. package/src/ui/views/input_area.ts +0 -255
  126. package/src/ui/views/message_list.ts +0 -443
  127. package/src/ui/views/status_bar.ts +0 -114
  128. package/src/ui/vue/index.ts +0 -53
  129. package/src/ui/web/frame_render.tsx +0 -148
  130. package/src/ui/web/index.tsx +0 -1
  131. package/src/ui/web/render.tsx +0 -41
  132. package/src/utils/clipboard.ts +0 -39
  133. package/src/utils/clipboard_image.ts +0 -40
  134. package/src/utils/diff.ts +0 -52
  135. package/src/utils/image_preview.ts +0 -36
  136. package/src/utils/models.ts +0 -98
  137. package/src/utils/path_complete.ts +0 -173
  138. package/src/utils/shell.ts +0 -72
  139. package/src/utils/spinner_frames.ts +0 -1
  140. package/src/utils/spinner_verbs.ts +0 -23
  141. package/src/utils/tool_summary.ts +0 -56
  142. package/src/utils/tool_trace.ts +0 -216
  143. package/src/utils/update.ts +0 -44
  144. package/src/utils/version.ts +0 -15
  145. package/src/web/index.html +0 -352
  146. package/src/web/mirror-favicon.svg +0 -4
  147. package/src/web/mirror.html +0 -641
  148. package/src/web/mirror_hook.ts +0 -25
  149. package/src/web/mirror_server.ts +0 -204
  150. package/tsconfig.json +0 -22
  151. package/vite.config.ts +0 -363
@@ -1,71 +0,0 @@
1
- import React, { useRef, useMemo } from 'react';
2
- import { Message } from '../types.js';
3
- import { InkNode } from '../ui/ink/index.js';
4
- import { buildMessageListView } from '../ui/views/message_list.js';
5
-
6
- interface MessageListProps {
7
- messages: Message[];
8
- height?: number;
9
- maxMessages?: number;
10
- debug?: boolean;
11
- expandToolOutputs?: boolean;
12
- scrollback?: boolean;
13
- }
14
-
15
- export const MessageList: React.FC<MessageListProps> = ({
16
- messages,
17
- height,
18
- maxMessages = 50,
19
- debug = false,
20
- expandToolOutputs = false,
21
- scrollback = false
22
- }) => {
23
- // In scrollback mode, track which messages have been rendered to avoid duplication
24
- const renderedIdsRef = useRef<Set<string>>(new Set());
25
-
26
- // Filter to only new, complete messages in scrollback mode
27
- const messagesToRender = useMemo(() => {
28
- if (!scrollback) {
29
- return messages;
30
- }
31
-
32
- // In scrollback mode, only render messages that:
33
- // 1. Are NOT currently streaming (wait for completion)
34
- // 2. Haven't been rendered yet
35
- const newMessages: Message[] = [];
36
- for (const msg of messages) {
37
- // Skip streaming messages - we'll render them when complete
38
- if (msg.isStreaming) {
39
- continue;
40
- }
41
-
42
- // Skip already rendered messages
43
- if (renderedIdsRef.current.has(msg.id)) {
44
- continue;
45
- }
46
-
47
- // This is a new, complete message - render it
48
- newMessages.push(msg);
49
- // Mark as rendered immediately
50
- renderedIdsRef.current.add(msg.id);
51
- }
52
- return newMessages;
53
- }, [messages, scrollback]);
54
-
55
- // Don't render anything if there are no new messages in scrollback mode
56
- if (scrollback && messagesToRender.length === 0) {
57
- return null;
58
- }
59
-
60
- const node = buildMessageListView({
61
- messages: messagesToRender,
62
- height,
63
- maxMessages,
64
- debug,
65
- expandToolOutputs,
66
- scrollback
67
- });
68
- return <InkNode node={node} />;
69
- };
70
-
71
- export default MessageList;
@@ -1,59 +0,0 @@
1
- import React from 'react';
2
- import { Box, Text } from 'ink';
3
- import { Message } from '../types.js';
4
-
5
- interface SingleMessageProps {
6
- message: Message;
7
- expandToolOutputs?: boolean;
8
- }
9
-
10
- interface RoleConfig {
11
- icon: string;
12
- color: string;
13
- label: string;
14
- }
15
-
16
- const roleConfigs: Record<string, RoleConfig> = {
17
- user: { icon: '❯', color: 'blue', label: 'You' },
18
- assistant: { icon: '◆', color: 'magenta', label: 'Zerg' },
19
- tool: { icon: '⏺', color: 'yellow', label: 'Trace' },
20
- system: { icon: '●', color: 'gray', label: 'System' }
21
- };
22
-
23
- function formatTime(date: Date): string {
24
- return date.toLocaleTimeString('en-US', {
25
- hour: '2-digit',
26
- minute: '2-digit',
27
- hour12: false
28
- });
29
- }
30
-
31
- export const SingleMessage: React.FC<SingleMessageProps> = ({
32
- message,
33
- expandToolOutputs = false
34
- }) => {
35
- const config = roleConfigs[message.role] || roleConfigs.system;
36
- const toolOutput = message.metadata && (message.metadata as Record<string, any>).toolOutput;
37
- const content = toolOutput && expandToolOutputs && toolOutput.full
38
- ? toolOutput.full
39
- : toolOutput && toolOutput.preview
40
- ? toolOutput.preview
41
- : message.content;
42
-
43
- return (
44
- <Box flexDirection="column" marginY={1} paddingX={1}>
45
- <Box flexDirection="row">
46
- <Text color={config.color} bold>{config.icon} {config.label}</Text>
47
- <Text color="gray" dimColor> • {formatTime(message.timestamp)}</Text>
48
- {message.isStreaming && <Text color="yellow" bold> ▌</Text>}
49
- </Box>
50
- <Box flexDirection="column" marginLeft={2}>
51
- {content.split('\n').map((line: string, i: number) => (
52
- <Text key={i}>{line}</Text>
53
- ))}
54
- </Box>
55
- </Box>
56
- );
57
- };
58
-
59
- export default SingleMessage;
@@ -1,55 +0,0 @@
1
- import React from 'react';
2
- import { AgentState } from '../types.js';
3
- import { InkNode } from '../ui/ink/index.js';
4
- import { buildStatusBarView } from '../ui/views/status_bar.js';
5
-
6
- interface StatusBarProps {
7
- state: AgentState;
8
- sessionId?: string;
9
- version?: string;
10
- connectionStatus?: 'connected' | 'disconnected' | 'connecting';
11
- contextLength?: number;
12
- contextEstimated?: boolean;
13
- provider?: string;
14
- model?: string;
15
- emulationId?: string;
16
- inputMode?: 'queue' | 'interrupt';
17
- toast?: string | null;
18
- spinnerLabel?: string | null;
19
- debug?: boolean;
20
- }
21
-
22
- export const StatusBar: React.FC<StatusBarProps> = ({
23
- state,
24
- sessionId,
25
- version = '0.1.0',
26
- connectionStatus = 'connected',
27
- contextLength,
28
- contextEstimated,
29
- provider,
30
- model,
31
- emulationId,
32
- inputMode,
33
- toast,
34
- spinnerLabel,
35
- debug = false
36
- }) => {
37
- const node = buildStatusBarView({
38
- state,
39
- sessionId,
40
- version,
41
- connectionStatus,
42
- contextLength,
43
- contextEstimated,
44
- provider,
45
- model,
46
- emulationId,
47
- inputMode,
48
- toast,
49
- spinnerLabel,
50
- debug
51
- });
52
- return <InkNode node={node} />;
53
- };
54
-
55
- export default StatusBar;
@@ -1,8 +0,0 @@
1
- // Component exports
2
- export { Header } from './Header.js';
3
- export { MessageList } from './MessageList.js';
4
- export { SingleMessage } from './SingleMessage.js';
5
- export { InputArea } from './InputArea.js';
6
- export { StatusBar } from './StatusBar.js';
7
- export { FullScreen, useScreenSize } from './FullScreen.js';
8
- export { ActivityLine } from './ActivityLine.js';
@@ -1,12 +0,0 @@
1
- export interface ZTCConfig {
2
- apiKey?: string;
3
- apiKeys?: Record<string, string>;
4
- provider?: string;
5
- openaiCompatibleBaseUrl?: string;
6
- model: string;
7
- maxTokens: number;
8
- zergEndpoint?: string;
9
- emulationId?: string;
10
- spinnerVerbs?: string[];
11
- toolPermissions?: Partial<Record<'file_read' | 'file_write' | 'shell_exec' | 'network', boolean>>;
12
- }
package/src/config.ts DELETED
@@ -1,186 +0,0 @@
1
- import { homedir } from 'os';
2
- import { join } from 'path';
3
- import { readFile, writeFile, mkdir } from 'fs/promises';
4
-
5
- import { ZTCConfig } from './config/types.js';
6
- import { DEFAULT_SPINNER_VERBS } from './utils/spinner_verbs.js';
7
-
8
- // --- Configuration Store ---
9
-
10
- const DEFAULT_CONFIG: ZTCConfig = {
11
- apiKey: process.env.ANTHROPIC_API_KEY,
12
- apiKeys: undefined,
13
- provider: 'anthropic',
14
- openaiCompatibleBaseUrl: undefined,
15
- model: 'claude-opus-4-20250514',
16
- maxTokens: 4096,
17
- zergEndpoint: undefined,
18
- emulationId: undefined,
19
- spinnerVerbs: DEFAULT_SPINNER_VERBS,
20
- toolPermissions: {
21
- file_read: true,
22
- file_write: true,
23
- shell_exec: true,
24
- network: true
25
- }
26
- };
27
-
28
- const CONFIG_DIR = join(homedir(), '.ztc');
29
- const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
30
-
31
- class ConfigStore {
32
- private config: ZTCConfig = { ...DEFAULT_CONFIG };
33
- private loaded = false;
34
-
35
- private applyEnvOverrides(): void {
36
- if (process.env.ANTHROPIC_API_KEY) {
37
- this.config.apiKey = process.env.ANTHROPIC_API_KEY;
38
- }
39
- }
40
-
41
- async load(force = false): Promise<ZTCConfig> {
42
- if (this.loaded && !force) return this.config;
43
-
44
- try {
45
- const data = await readFile(CONFIG_FILE, 'utf-8');
46
- const saved = JSON.parse(data) as Partial<ZTCConfig>;
47
- this.config = { ...DEFAULT_CONFIG, ...saved };
48
- if (this.config.model === 'claude-opus-4-5-20250514') {
49
- this.config.model = 'claude-opus-4-20250514';
50
- }
51
- if (!this.config.spinnerVerbs) {
52
- this.config.spinnerVerbs = DEFAULT_SPINNER_VERBS;
53
- }
54
- if (!this.config.toolPermissions) {
55
- this.config.toolPermissions = { ...DEFAULT_CONFIG.toolPermissions };
56
- }
57
- this.applyEnvOverrides();
58
- } catch {
59
- // File doesn't exist or is invalid, use defaults
60
- this.config = { ...DEFAULT_CONFIG };
61
- }
62
-
63
- this.loaded = true;
64
- return this.config;
65
- }
66
-
67
- async refresh(): Promise<void> {
68
- await this.load(true);
69
- }
70
-
71
- async save(): Promise<void> {
72
- try {
73
- await mkdir(CONFIG_DIR, { recursive: true });
74
-
75
- // Don't persist API key if it came from env
76
- const toSave: Partial<ZTCConfig> = { ...this.config };
77
- if (process.env.ANTHROPIC_API_KEY === this.config.apiKey) {
78
- delete toSave.apiKey;
79
- }
80
-
81
- await writeFile(CONFIG_FILE, JSON.stringify(toSave, null, 2), 'utf-8');
82
- } catch (err) {
83
- console.error('Failed to save config:', err);
84
- }
85
- }
86
-
87
- get(): ZTCConfig {
88
- return this.config;
89
- }
90
-
91
- set<K extends keyof ZTCConfig>(key: K, value: ZTCConfig[K]): void {
92
- this.config[key] = value;
93
- }
94
-
95
- setAll(next: Partial<ZTCConfig>): void {
96
- this.config = { ...DEFAULT_CONFIG, ...this.config, ...next };
97
- if (this.config.model === 'claude-opus-4-5-20250514') {
98
- this.config.model = 'claude-opus-4-20250514';
99
- }
100
- if (!this.config.spinnerVerbs) {
101
- this.config.spinnerVerbs = DEFAULT_SPINNER_VERBS;
102
- }
103
- if (!this.config.toolPermissions) {
104
- this.config.toolPermissions = { ...DEFAULT_CONFIG.toolPermissions };
105
- }
106
- this.applyEnvOverrides();
107
- this.loaded = true;
108
- }
109
-
110
- hasApiKey(): boolean {
111
- const key = this.getApiKey();
112
- return !!key && key.length > 0;
113
- }
114
-
115
- getApiKey(provider?: string): string | undefined {
116
- const chosen = provider || this.getProvider();
117
- const envKey = this.getEnvKey(chosen);
118
- if (envKey) return envKey;
119
- if (this.config.apiKeys && this.config.apiKeys[chosen]) return this.config.apiKeys[chosen];
120
- return this.config.apiKey;
121
- }
122
-
123
- setApiKey(key: string, provider?: string): void {
124
- const chosen = provider || this.getProvider();
125
- if (!this.config.apiKeys) {
126
- this.config.apiKeys = {};
127
- }
128
- this.config.apiKeys[chosen] = key;
129
- if (chosen === 'anthropic') {
130
- this.config.apiKey = key;
131
- }
132
- }
133
-
134
- getEmulationId(): string | undefined {
135
- return this.config.emulationId;
136
- }
137
-
138
- setEmulationId(id: string | undefined): void {
139
- this.config.emulationId = id;
140
- }
141
-
142
- getMaskedApiKey(): string {
143
- const key = this.getApiKey();
144
- if (!key) return '(not set)';
145
- if (key.length < 12) return '****';
146
- return `${key.slice(0, 7)}...${key.slice(-4)}`;
147
- }
148
-
149
- getProvider(): string {
150
- return this.config.provider || 'anthropic';
151
- }
152
-
153
- setProvider(provider: string): void {
154
- this.config.provider = provider;
155
- }
156
-
157
- getOpenAICompatibleBaseUrl(): string | undefined {
158
- return this.config.openaiCompatibleBaseUrl;
159
- }
160
-
161
- setOpenAICompatibleBaseUrl(url: string | undefined): void {
162
- this.config.openaiCompatibleBaseUrl = url;
163
- }
164
-
165
- private getEnvKey(provider: string): string | undefined {
166
- const map: Record<string, string | undefined> = {
167
- anthropic: process.env.ANTHROPIC_API_KEY,
168
- openai: process.env.OPENAI_API_KEY,
169
- gemini: process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY,
170
- inception: process.env.INCEPTION_API_KEY,
171
- openai_compatible: process.env.OPENAI_COMPAT_API_KEY
172
- };
173
- return map[provider];
174
- }
175
-
176
- getConfigPath(): string {
177
- return CONFIG_FILE;
178
- }
179
-
180
- get locationLabel(): string {
181
- return CONFIG_FILE;
182
- }
183
- }
184
-
185
- export const configStore = new ConfigStore();
186
- export default configStore;
@@ -1,14 +0,0 @@
1
- import { appendFileSync } from 'fs';
2
-
3
- const enabled = process.env.ZTC_DEBUG_RENDER === '1';
4
- const logPath = process.env.ZTC_DEBUG_RENDER_LOG || '/tmp/ztc_render.log';
5
-
6
- export function debugLog(message: string): void {
7
- if (!enabled) return;
8
- const line = `[${new Date().toISOString()}] ${message}\n`;
9
- try {
10
- appendFileSync(logPath, line, 'utf-8');
11
- } catch {
12
- // Ignore logging failures
13
- }
14
- }
@@ -1,24 +0,0 @@
1
- ## Emulation Layer
2
-
3
- This module loads third-party tool prompts (e.g., Claude Code, Codex CLI) and exposes them as selectable emulation profiles.
4
-
5
- ### Data Source
6
- The content is extracted from the `x1xhlol/system-prompts-and-models-of-ai-tools` repository and stored locally in:
7
- `~/.ztc/emulations/x1xhlol/`
8
-
9
- You can override the base path with `ZTC_EMULATION_DIR` (useful for tests or custom fixtures).
10
-
11
- ### Fixture Setup
12
- For tests, point `ZTC_EMULATION_DIR` at `tests/fixtures/emulations/x1xhlol` to use the bundled fixture data.
13
-
14
- To populate your local emulation cache:
15
- - `npm run emulation:init`
16
-
17
- ### Usage
18
- - `/emulation list` to see available profiles
19
- - `/emulation set <id>` to activate
20
- - `/emulation show` to see the current profile
21
-
22
- ### Notes
23
- - The emulation layer currently wires the **system prompt** into the agent.
24
- - Tool schemas are loaded and stored for future use, but not yet mapped to runtime tools.
@@ -1,82 +0,0 @@
1
- import { readFileSync, existsSync } from 'fs';
2
- import { resolve, join } from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { homedir } from 'os';
5
- import { EmulationProfile } from './types.js';
6
-
7
- interface EmulationSource {
8
- id: string;
9
- name: string;
10
- description: string;
11
- promptPath: string;
12
- toolsPath?: string;
13
- }
14
-
15
- const sources: EmulationSource[] = [
16
- {
17
- id: 'claude-code',
18
- name: 'Claude Code',
19
- description: 'Anthropic Claude Code CLI emulation',
20
- promptPath: 'Anthropic/Claude Code/Prompt.txt',
21
- toolsPath: 'Anthropic/Claude Code/Tools.json'
22
- },
23
- {
24
- id: 'codex-cli-system',
25
- name: 'Codex CLI (System Prompt 2025-08-20)',
26
- description: 'OpenAI Codex CLI system prompt emulation',
27
- promptPath: 'Open Source prompts/Codex CLI/openai-codex-cli-system-prompt-20250820.txt'
28
- },
29
- {
30
- id: 'codex-cli',
31
- name: 'Codex CLI (Prompt)',
32
- description: 'OpenAI Codex CLI prompt emulation',
33
- promptPath: 'Open Source prompts/Codex CLI/Prompt.txt'
34
- }
35
- ];
36
-
37
- function resolveBaseDir(): string {
38
- const override = process.env.ZTC_EMULATION_DIR;
39
- if (override && override.trim().length > 0) {
40
- return resolve(override);
41
- }
42
- const candidates = [
43
- join(homedir(), '.ztc', 'emulations', 'x1xhlol'),
44
- resolve(process.cwd(), 'emulations/x1xhlol'),
45
- resolve(process.cwd(), 'ztc/emulations/x1xhlol'),
46
- resolve(fileURLToPath(new URL('../../emulations/x1xhlol', import.meta.url)))
47
- ];
48
- for (const candidate of candidates) {
49
- if (existsSync(candidate)) {
50
- return candidate;
51
- }
52
- }
53
- return candidates[0];
54
- }
55
-
56
- export function loadEmulationProfiles(): EmulationProfile[] {
57
- const baseDir = resolveBaseDir();
58
-
59
- return sources.flatMap(source => {
60
- const promptFile = resolve(baseDir, source.promptPath);
61
- if (!existsSync(promptFile)) {
62
- return [];
63
- }
64
- const prompt = readFileSync(promptFile, 'utf-8');
65
- const toolsFile = source.toolsPath ? resolve(baseDir, source.toolsPath) : undefined;
66
- const tools = toolsFile && existsSync(toolsFile)
67
- ? JSON.parse(readFileSync(toolsFile, 'utf-8'))
68
- : undefined;
69
-
70
- return [{
71
- id: source.id,
72
- name: source.name,
73
- description: source.description,
74
- systemPrompt: prompt,
75
- tools
76
- }];
77
- });
78
- }
79
-
80
- export function getEmulationProfile(id: string): EmulationProfile | undefined {
81
- return loadEmulationProfiles().find(profile => profile.id === id);
82
- }
@@ -1,8 +0,0 @@
1
- export type TraceStyle = 'claude_code' | 'codex' | 'plain';
2
-
3
- export function getTraceStyle(emulationId?: string): TraceStyle {
4
- if (!emulationId) return 'plain';
5
- if (emulationId === 'claude-code') return 'claude_code';
6
- if (emulationId.startsWith('codex')) return 'codex';
7
- return 'plain';
8
- }
@@ -1,7 +0,0 @@
1
- export interface EmulationProfile {
2
- id: string;
3
- name: string;
4
- description: string;
5
- systemPrompt: string;
6
- tools?: Record<string, unknown>;
7
- }
@@ -1,36 +0,0 @@
1
- import { Skill } from './types.js';
2
-
3
- export function buildSkillPrompt(skills: Skill[]): string {
4
- if (skills.length === 0) return '';
5
- const blocks = skills.map(skill => {
6
- const header = `Skill: ${skill.name}`;
7
- const description = skill.description ? `Description: ${skill.description}` : '';
8
- const instructions = skill.instructions.trim();
9
- return [header, description, instructions].filter(Boolean).join('\n');
10
- });
11
- return ['# Skills', ...blocks].join('\n\n');
12
- }
13
-
14
- export function autoActivateSkills(message: string, skills: Skill[]): Skill[] {
15
- const haystack = message.toLowerCase();
16
- return skills.filter(skill => {
17
- const name = skill.name.toLowerCase();
18
- const id = skill.id.toLowerCase();
19
- if (haystack.includes(name) || haystack.includes(id)) return true;
20
- if (skill.keywords) {
21
- return skill.keywords.some(keyword => haystack.includes(keyword.toLowerCase()));
22
- }
23
- return false;
24
- });
25
- }
26
-
27
- export function formatSkillList(skills: Skill[]): string {
28
- if (skills.length === 0) return 'No skills found.';
29
- const lines = skills
30
- .sort((a, b) => a.name.localeCompare(b.name))
31
- .map(skill => {
32
- const source = skill.sourceRoot.includes('.claude') ? 'claude' : 'ztc';
33
- return ` ${skill.id} - ${skill.name}${skill.description ? `: ${skill.description}` : ''} (${source})`;
34
- });
35
- return ['Available skills:', ...lines].join('\n');
36
- }