@xortex/xcode 3.1.1 → 3.1.2

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/bin/xcode CHANGED
@@ -46,7 +46,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
46
46
  const args = process.argv.slice(2);
47
47
 
48
48
  if (args[0] === '--version' || args[0] === '-v' || args[0] === '-V') {
49
- console.log('xcode v3.1.1 — AI coding assistant with XMem memory');
49
+ console.log('xcode v3.1.2 — AI coding assistant with XMem memory');
50
50
  process.exit(0);
51
51
  }
52
52
 
package/costHook.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { useEffect } from 'react'
2
+ import { formatTotalCost, saveCurrentSessionCosts } from './cost-tracker.js'
3
+ import { hasConsoleBillingAccess } from './utils/billing.js'
4
+ import type { FpsMetrics } from './utils/fpsTracker.js'
5
+
6
+ export function useCostSummary(
7
+ getFpsMetrics?: () => FpsMetrics | undefined,
8
+ ): void {
9
+ useEffect(() => {
10
+ const f = () => {
11
+ if (hasConsoleBillingAccess()) {
12
+ process.stdout.write('\n' + formatTotalCost() + '\n')
13
+ }
14
+
15
+ saveCurrentSessionCosts(getFpsMetrics?.())
16
+ }
17
+ process.on('exit', f)
18
+ return () => {
19
+ process.off('exit', f)
20
+ }
21
+ }, [])
22
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Thin launchers for one-off dialog JSX sites in main.tsx.
3
+ * Each launcher dynamically imports its component and wires the `done` callback
4
+ * identically to the original inline call site. Zero behavior change.
5
+ *
6
+ * Part of the main.tsx React/JSX extraction effort. See sibling PRs
7
+ * perf/extract-interactive-helpers and perf/launch-repl.
8
+ */
9
+ import React from 'react';
10
+ import type { AssistantSession } from './assistant/sessionDiscovery.js';
11
+ import type { StatsStore } from './context/stats.js';
12
+ import type { Root } from './ink.js';
13
+ import { renderAndRun, showSetupDialog } from './interactiveHelpers.js';
14
+ import { KeybindingSetup } from './keybindings/KeybindingProviderSetup.js';
15
+ import type { AppState } from './state/AppStateStore.js';
16
+ import type { AgentMemoryScope } from './tools/AgentTool/agentMemory.js';
17
+ import type { TeleportRemoteResponse } from './utils/conversationRecovery.js';
18
+ import type { FpsMetrics } from './utils/fpsTracker.js';
19
+ import type { ValidationError } from './utils/settings/validation.js';
20
+
21
+ // Type-only access to ResumeConversation's Props via the module type.
22
+ // No runtime cost - erased at compile time.
23
+ type ResumeConversationProps = React.ComponentProps<typeof import('./screens/ResumeConversation.js').ResumeConversation>;
24
+
25
+ /**
26
+ * Site ~3173: SnapshotUpdateDialog (agent memory snapshot update prompt).
27
+ * Original callback wiring: onComplete={done}, onCancel={() => done('keep')}.
28
+ */
29
+ export async function launchSnapshotUpdateDialog(root: Root, props: {
30
+ agentType: string;
31
+ scope: AgentMemoryScope;
32
+ snapshotTimestamp: string;
33
+ }): Promise<'merge' | 'keep' | 'replace'> {
34
+ const {
35
+ SnapshotUpdateDialog
36
+ } = await import('./components/agents/SnapshotUpdateDialog.js');
37
+ return showSetupDialog<'merge' | 'keep' | 'replace'>(root, done => <SnapshotUpdateDialog agentType={props.agentType} scope={props.scope} snapshotTimestamp={props.snapshotTimestamp} onComplete={done} onCancel={() => done('keep')} />);
38
+ }
39
+
40
+ /**
41
+ * Site ~3250: InvalidSettingsDialog (settings validation errors).
42
+ * Original callback wiring: onContinue={done}, onExit passed through from caller.
43
+ */
44
+ export async function launchInvalidSettingsDialog(root: Root, props: {
45
+ settingsErrors: ValidationError[];
46
+ onExit: () => void;
47
+ }): Promise<void> {
48
+ const {
49
+ InvalidSettingsDialog
50
+ } = await import('./components/InvalidSettingsDialog.js');
51
+ return showSetupDialog(root, done => <InvalidSettingsDialog settingsErrors={props.settingsErrors} onContinue={done} onExit={props.onExit} />);
52
+ }
53
+
54
+ /**
55
+ * Site ~4229: AssistantSessionChooser (pick a bridge session to attach to).
56
+ * Original callback wiring: onSelect={id => done(id)}, onCancel={() => done(null)}.
57
+ */
58
+ export async function launchAssistantSessionChooser(root: Root, props: {
59
+ sessions: AssistantSession[];
60
+ }): Promise<string | null> {
61
+ const {
62
+ AssistantSessionChooser
63
+ } = await import('./assistant/AssistantSessionChooser.js');
64
+ return showSetupDialog<string | null>(root, done => <AssistantSessionChooser sessions={props.sessions} onSelect={id => done(id)} onCancel={() => done(null)} />);
65
+ }
66
+
67
+ /**
68
+ * `claude assistant` found zero sessions — show the same install wizard
69
+ * as `/assistant` when daemon.json is empty. Resolves to the installed dir on
70
+ * success, null on cancel. Rejects on install failure so the caller can
71
+ * distinguish errors from user cancellation.
72
+ */
73
+ export async function launchAssistantInstallWizard(root: Root): Promise<string | null> {
74
+ const {
75
+ NewInstallWizard,
76
+ computeDefaultInstallDir
77
+ } = await import('./commands/assistant/assistant.js');
78
+ const defaultDir = await computeDefaultInstallDir();
79
+ let rejectWithError: (reason: Error) => void;
80
+ const errorPromise = new Promise<never>((_, reject) => {
81
+ rejectWithError = reject;
82
+ });
83
+ const resultPromise = showSetupDialog<string | null>(root, done => <NewInstallWizard defaultDir={defaultDir} onInstalled={dir => done(dir)} onCancel={() => done(null)} onError={message => rejectWithError(new Error(`Installation failed: ${message}`))} />);
84
+ return Promise.race([resultPromise, errorPromise]);
85
+ }
86
+
87
+ /**
88
+ * Site ~4549: TeleportResumeWrapper (interactive teleport session picker).
89
+ * Original callback wiring: onComplete={done}, onCancel={() => done(null)}, source="cliArg".
90
+ */
91
+ export async function launchTeleportResumeWrapper(root: Root): Promise<TeleportRemoteResponse | null> {
92
+ const {
93
+ TeleportResumeWrapper
94
+ } = await import('./components/TeleportResumeWrapper.js');
95
+ return showSetupDialog<TeleportRemoteResponse | null>(root, done => <TeleportResumeWrapper onComplete={done} onCancel={() => done(null)} source="cliArg" />);
96
+ }
97
+
98
+ /**
99
+ * Site ~4597: TeleportRepoMismatchDialog (pick a local checkout of the target repo).
100
+ * Original callback wiring: onSelectPath={done}, onCancel={() => done(null)}.
101
+ */
102
+ export async function launchTeleportRepoMismatchDialog(root: Root, props: {
103
+ targetRepo: string;
104
+ initialPaths: string[];
105
+ }): Promise<string | null> {
106
+ const {
107
+ TeleportRepoMismatchDialog
108
+ } = await import('./components/TeleportRepoMismatchDialog.js');
109
+ return showSetupDialog<string | null>(root, done => <TeleportRepoMismatchDialog targetRepo={props.targetRepo} initialPaths={props.initialPaths} onSelectPath={done} onCancel={() => done(null)} />);
110
+ }
111
+
112
+ /**
113
+ * Site ~4903: ResumeConversation mount (interactive session picker).
114
+ * Uses renderAndRun, NOT showSetupDialog. Wraps in <App><KeybindingSetup>.
115
+ * Preserves original Promise.all parallelism between getWorktreePaths and imports.
116
+ */
117
+ export async function launchResumeChooser(root: Root, appProps: {
118
+ getFpsMetrics: () => FpsMetrics | undefined;
119
+ stats: StatsStore;
120
+ initialState: AppState;
121
+ }, worktreePathsPromise: Promise<string[]>, resumeProps: Omit<ResumeConversationProps, 'worktreePaths'>): Promise<void> {
122
+ const [worktreePaths, {
123
+ ResumeConversation
124
+ }, {
125
+ App
126
+ }] = await Promise.all([worktreePathsPromise, import('./screens/ResumeConversation.js'), import('./components/App.js')]);
127
+ await renderAndRun(root, <App getFpsMetrics={appProps.getFpsMetrics} stats={appProps.stats} initialState={appProps.initialState}>
128
+ <KeybindingSetup>
129
+ <ResumeConversation {...resumeProps} worktreePaths={worktreePaths} />
130
+ </KeybindingSetup>
131
+ </App>);
132
+ }
133
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkFzc2lzdGFudFNlc3Npb24iLCJTdGF0c1N0b3JlIiwiUm9vdCIsInJlbmRlckFuZFJ1biIsInNob3dTZXR1cERpYWxvZyIsIktleWJpbmRpbmdTZXR1cCIsIkFwcFN0YXRlIiwiQWdlbnRNZW1vcnlTY29wZSIsIlRlbGVwb3J0UmVtb3RlUmVzcG9uc2UiLCJGcHNNZXRyaWNzIiwiVmFsaWRhdGlvbkVycm9yIiwiUmVzdW1lQ29udmVyc2F0aW9uUHJvcHMiLCJDb21wb25lbnRQcm9wcyIsIlJlc3VtZUNvbnZlcnNhdGlvbiIsImxhdW5jaFNuYXBzaG90VXBkYXRlRGlhbG9nIiwicm9vdCIsInByb3BzIiwiYWdlbnRUeXBlIiwic2NvcGUiLCJzbmFwc2hvdFRpbWVzdGFtcCIsIlByb21pc2UiLCJTbmFwc2hvdFVwZGF0ZURpYWxvZyIsImRvbmUiLCJsYXVuY2hJbnZhbGlkU2V0dGluZ3NEaWFsb2ciLCJzZXR0aW5nc0Vycm9ycyIsIm9uRXhpdCIsIkludmFsaWRTZXR0aW5nc0RpYWxvZyIsImxhdW5jaEFzc2lzdGFudFNlc3Npb25DaG9vc2VyIiwic2Vzc2lvbnMiLCJBc3Npc3RhbnRTZXNzaW9uQ2hvb3NlciIsImlkIiwibGF1bmNoQXNzaXN0YW50SW5zdGFsbFdpemFyZCIsIk5ld0luc3RhbGxXaXphcmQiLCJjb21wdXRlRGVmYXVsdEluc3RhbGxEaXIiLCJkZWZhdWx0RGlyIiwicmVqZWN0V2l0aEVycm9yIiwicmVhc29uIiwiRXJyb3IiLCJlcnJvclByb21pc2UiLCJfIiwicmVqZWN0IiwicmVzdWx0UHJvbWlzZSIsImRpciIsIm1lc3NhZ2UiLCJyYWNlIiwibGF1bmNoVGVsZXBvcnRSZXN1bWVXcmFwcGVyIiwiVGVsZXBvcnRSZXN1bWVXcmFwcGVyIiwibGF1bmNoVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2ciLCJ0YXJnZXRSZXBvIiwiaW5pdGlhbFBhdGhzIiwiVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2ciLCJsYXVuY2hSZXN1bWVDaG9vc2VyIiwiYXBwUHJvcHMiLCJnZXRGcHNNZXRyaWNzIiwic3RhdHMiLCJpbml0aWFsU3RhdGUiLCJ3b3JrdHJlZVBhdGhzUHJvbWlzZSIsInJlc3VtZVByb3BzIiwiT21pdCIsIndvcmt0cmVlUGF0aHMiLCJBcHAiLCJhbGwiXSwic291cmNlcyI6WyJkaWFsb2dMYXVuY2hlcnMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpbiBsYXVuY2hlcnMgZm9yIG9uZS1vZmYgZGlhbG9nIEpTWCBzaXRlcyBpbiBtYWluLnRzeC5cbiAqIEVhY2ggbGF1bmNoZXIgZHluYW1pY2FsbHkgaW1wb3J0cyBpdHMgY29tcG9uZW50IGFuZCB3aXJlcyB0aGUgYGRvbmVgIGNhbGxiYWNrXG4gKiBpZGVudGljYWxseSB0byB0aGUgb3JpZ2luYWwgaW5saW5lIGNhbGwgc2l0ZS4gWmVybyBiZWhhdmlvciBjaGFuZ2UuXG4gKlxuICogUGFydCBvZiB0aGUgbWFpbi50c3ggUmVhY3QvSlNYIGV4dHJhY3Rpb24gZWZmb3J0LiBTZWUgc2libGluZyBQUnNcbiAqIHBlcmYvZXh0cmFjdC1pbnRlcmFjdGl2ZS1oZWxwZXJzIGFuZCBwZXJmL2xhdW5jaC1yZXBsLlxuICovXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IEFzc2lzdGFudFNlc3Npb24gfSBmcm9tICcuL2Fzc2lzdGFudC9zZXNzaW9uRGlzY292ZXJ5LmpzJ1xuaW1wb3J0IHR5cGUgeyBTdGF0c1N0b3JlIH0gZnJvbSAnLi9jb250ZXh0L3N0YXRzLmpzJ1xuaW1wb3J0IHR5cGUgeyBSb290IH0gZnJvbSAnLi9pbmsuanMnXG5pbXBvcnQgeyByZW5kZXJBbmRSdW4sIHNob3dTZXR1cERpYWxvZyB9IGZyb20gJy4vaW50ZXJhY3RpdmVIZWxwZXJzLmpzJ1xuaW1wb3J0IHsgS2V5YmluZGluZ1NldHVwIH0gZnJvbSAnLi9rZXliaW5kaW5ncy9LZXliaW5kaW5nUHJvdmlkZXJTZXR1cC5qcydcbmltcG9ydCB0eXBlIHsgQXBwU3RhdGUgfSBmcm9tICcuL3N0YXRlL0FwcFN0YXRlU3RvcmUuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50TWVtb3J5U2NvcGUgfSBmcm9tICcuL3Rvb2xzL0FnZW50VG9vbC9hZ2VudE1lbW9yeS5qcydcbmltcG9ydCB0eXBlIHsgVGVsZXBvcnRSZW1vdGVSZXNwb25zZSB9IGZyb20gJy4vdXRpbHMvY29udmVyc2F0aW9uUmVjb3ZlcnkuanMnXG5pbXBvcnQgdHlwZSB7IEZwc01ldHJpY3MgfSBmcm9tICcuL3V0aWxzL2Zwc1RyYWNrZXIuanMnXG5pbXBvcnQgdHlwZSB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4vdXRpbHMvc2V0dGluZ3MvdmFsaWRhdGlvbi5qcydcblxuLy8gVHlwZS1vbmx5IGFjY2VzcyB0byBSZXN1bWVDb252ZXJzYXRpb24ncyBQcm9wcyB2aWEgdGhlIG1vZHVsZSB0eXBlLlxuLy8gTm8gcnVudGltZSBjb3N0IC0gZXJhc2VkIGF0IGNvbXBpbGUgdGltZS5cbnR5cGUgUmVzdW1lQ29udmVyc2F0aW9uUHJvcHMgPSBSZWFjdC5Db21wb25lbnRQcm9wczxcbiAgdHlwZW9mIGltcG9ydCgnLi9zY3JlZW5zL1Jlc3VtZUNvbnZlcnNhdGlvbi5qcycpLlJlc3VtZUNvbnZlcnNhdGlvblxuPlxuXG4vKipcbiAqIFNpdGUgfjMxNzM6IFNuYXBzaG90VXBkYXRlRGlhbG9nIChhZ2VudCBtZW1vcnkgc25hcHNob3QgdXBkYXRlIHByb21wdCkuXG4gKiBPcmlnaW5hbCBjYWxsYmFjayB3aXJpbmc6IG9uQ29tcGxldGU9e2RvbmV9LCBvbkNhbmNlbD17KCkgPT4gZG9uZSgna2VlcCcpfS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxhdW5jaFNuYXBzaG90VXBkYXRlRGlhbG9nKFxuICByb290OiBSb290LFxuICBwcm9wczoge1xuICAgIGFnZW50VHlwZTogc3RyaW5nXG4gICAgc2NvcGU6IEFnZW50TWVtb3J5U2NvcGVcbiAgICBzbmFwc2hvdFRpbWVzdGFtcDogc3RyaW5nXG4gIH0sXG4pOiBQcm9taXNlPCdtZXJnZScgfCAna2VlcCcgfCAncmVwbGFjZSc+IHtcbiAgY29uc3QgeyBTbmFwc2hvdFVwZGF0ZURpYWxvZyB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICcuL2NvbXBvbmVudHMvYWdlbnRzL1NuYXBzaG90VXBkYXRlRGlhbG9nLmpzJ1xuICApXG4gIHJldHVybiBzaG93U2V0dXBEaWFsb2c8J21lcmdlJyB8ICdrZWVwJyB8ICdyZXBsYWNlJz4ocm9vdCwgZG9uZSA9PiAoXG4gICAgPFNuYXBzaG90VXBkYXRlRGlhbG9nXG4gICAgICBhZ2VudFR5cGU9e3Byb3BzLmFnZW50VHlwZX1cbiAgICAgIHNjb3BlPXtwcm9wcy5zY29wZX1cbiAgICAgIHNuYXBzaG90VGltZXN0YW1wPXtwcm9wcy5zbmFwc2hvdFRpbWVzdGFtcH1cbiAgICAgIG9uQ29tcGxldGU9e2RvbmV9XG4gICAgICBvbkNhbmNlbD17KCkgPT4gZG9uZSgna2VlcCcpfVxuICAgIC8+XG4gICkpXG59XG5cbi8qKlxuICogU2l0ZSB+MzI1MDogSW52YWxpZFNldHRpbmdzRGlhbG9nIChzZXR0aW5ncyB2YWxpZGF0aW9uIGVycm9ycykuXG4gKiBPcmlnaW5hbCBjYWxsYmFjayB3aXJpbmc6IG9uQ29udGludWU9e2RvbmV9LCBvbkV4aXQgcGFzc2VkIHRocm91Z2ggZnJvbSBjYWxsZXIuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsYXVuY2hJbnZhbGlkU2V0dGluZ3NEaWFsb2coXG4gIHJvb3Q6IFJvb3QsXG4gIHByb3BzOiB7XG4gICAgc2V0dGluZ3NFcnJvcnM6IFZhbGlkYXRpb25FcnJvcltdXG4gICAgb25FeGl0OiAoKSA9PiB2b2lkXG4gIH0sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBJbnZhbGlkU2V0dGluZ3NEaWFsb2cgfSA9IGF3YWl0IGltcG9ydChcbiAgICAnLi9jb21wb25lbnRzL0ludmFsaWRTZXR0aW5nc0RpYWxvZy5qcydcbiAgKVxuICByZXR1cm4gc2hvd1NldHVwRGlhbG9nKHJvb3QsIGRvbmUgPT4gKFxuICAgIDxJbnZhbGlkU2V0dGluZ3NEaWFsb2dcbiAgICAgIHNldHRpbmdzRXJyb3JzPXtwcm9wcy5zZXR0aW5nc0Vycm9yc31cbiAgICAgIG9uQ29udGludWU9e2RvbmV9XG4gICAgICBvbkV4aXQ9e3Byb3BzLm9uRXhpdH1cbiAgICAvPlxuICApKVxufVxuXG4vKipcbiAqIFNpdGUgfjQyMjk6IEFzc2lzdGFudFNlc3Npb25DaG9vc2VyIChwaWNrIGEgYnJpZGdlIHNlc3Npb24gdG8gYXR0YWNoIHRvKS5cbiAqIE9yaWdpbmFsIGNhbGxiYWNrIHdpcmluZzogb25TZWxlY3Q9e2lkID0+IGRvbmUoaWQpfSwgb25DYW5jZWw9eygpID0+IGRvbmUobnVsbCl9LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGF1bmNoQXNzaXN0YW50U2Vzc2lvbkNob29zZXIoXG4gIHJvb3Q6IFJvb3QsXG4gIHByb3BzOiB7IHNlc3Npb25zOiBBc3Npc3RhbnRTZXNzaW9uW10gfSxcbik6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICBjb25zdCB7IEFzc2lzdGFudFNlc3Npb25DaG9vc2VyIH0gPSBhd2FpdCBpbXBvcnQoXG4gICAgJy4vYXNzaXN0YW50L0Fzc2lzdGFudFNlc3Npb25DaG9vc2VyLmpzJ1xuICApXG4gIHJldHVybiBzaG93U2V0dXBEaWFsb2c8c3RyaW5nIHwgbnVsbD4ocm9vdCwgZG9uZSA9PiAoXG4gICAgPEFzc2lzdGFudFNlc3Npb25DaG9vc2VyXG4gICAgICBzZXNzaW9ucz17cHJvcHMuc2Vzc2lvbnN9XG4gICAgICBvblNlbGVjdD17aWQgPT4gZG9uZShpZCl9XG4gICAgICBvbkNhbmNlbD17KCkgPT4gZG9uZShudWxsKX1cbiAgICAvPlxuICApKVxufVxuXG4vKipcbiAqIGBjbGF1ZGUgYXNzaXN0YW50YCBmb3VuZCB6ZXJvIHNlc3Npb25zIOKAlCBzaG93IHRoZSBzYW1lIGluc3RhbGwgd2l6YXJkXG4gKiBhcyBgL2Fzc2lzdGFudGAgd2hlbiBkYWVtb24uanNvbiBpcyBlbXB0eS4gUmVzb2x2ZXMgdG8gdGhlIGluc3RhbGxlZCBkaXIgb25cbiAqIHN1Y2Nlc3MsIG51bGwgb24gY2FuY2VsLiBSZWplY3RzIG9uIGluc3RhbGwgZmFpbHVyZSBzbyB0aGUgY2FsbGVyIGNhblxuICogZGlzdGluZ3Vpc2ggZXJyb3JzIGZyb20gdXNlciBjYW5jZWxsYXRpb24uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsYXVuY2hBc3Npc3RhbnRJbnN0YWxsV2l6YXJkKFxuICByb290OiBSb290LFxuKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gIGNvbnN0IHsgTmV3SW5zdGFsbFdpemFyZCwgY29tcHV0ZURlZmF1bHRJbnN0YWxsRGlyIH0gPSBhd2FpdCBpbXBvcnQoXG4gICAgJy4vY29tbWFuZHMvYXNzaXN0YW50L2Fzc2lzdGFudC5qcydcbiAgKVxuICBjb25zdCBkZWZhdWx0RGlyID0gYXdhaXQgY29tcHV0ZURlZmF1bHRJbnN0YWxsRGlyKClcbiAgbGV0IHJlamVjdFdpdGhFcnJvcjogKHJlYXNvbjogRXJyb3IpID0+IHZvaWRcbiAgY29uc3QgZXJyb3JQcm9taXNlID0gbmV3IFByb21pc2U8bmV2ZXI+KChfLCByZWplY3QpID0+IHtcbiAgICByZWplY3RXaXRoRXJyb3IgPSByZWplY3RcbiAgfSlcbiAgY29uc3QgcmVzdWx0UHJvbWlzZSA9IHNob3dTZXR1cERpYWxvZzxzdHJpbmcgfCBudWxsPihyb290LCBkb25lID0+IChcbiAgICA8TmV3SW5zdGFsbFdpemFyZFxuICAgICAgZGVmYXVsdERpcj17ZGVmYXVsdERpcn1cbiAgICAgIG9uSW5zdGFsbGVkPXtkaXIgPT4gZG9uZShkaXIpfVxuICAgICAgb25DYW5jZWw9eygpID0+IGRvbmUobnVsbCl9XG4gICAgICBvbkVycm9yPXttZXNzYWdlID0+XG4gICAgICAgIHJlamVjdFdpdGhFcnJvcihuZXcgRXJyb3IoYEluc3RhbGxhdGlvbiBmYWlsZWQ6ICR7bWVzc2FnZX1gKSlcbiAgICAgIH1cbiAgICAvPlxuICApKVxuICByZXR1cm4gUHJvbWlzZS5yYWNlKFtyZXN1bHRQcm9taXNlLCBlcnJvclByb21pc2VdKVxufVxuXG4vKipcbiAqIFNpdGUgfjQ1NDk6IFRlbGVwb3J0UmVzdW1lV3JhcHBlciAoaW50ZXJhY3RpdmUgdGVsZXBvcnQgc2Vzc2lvbiBwaWNrZXIpLlxuICogT3JpZ2luYWwgY2FsbGJhY2sgd2lyaW5nOiBvbkNvbXBsZXRlPXtkb25lfSwgb25DYW5jZWw9eygpID0+IGRvbmUobnVsbCl9LCBzb3VyY2U9XCJjbGlBcmdcIi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxhdW5jaFRlbGVwb3J0UmVzdW1lV3JhcHBlcihcbiAgcm9vdDogUm9vdCxcbik6IFByb21pc2U8VGVsZXBvcnRSZW1vdGVSZXNwb25zZSB8IG51bGw+IHtcbiAgY29uc3QgeyBUZWxlcG9ydFJlc3VtZVdyYXBwZXIgfSA9IGF3YWl0IGltcG9ydChcbiAgICAnLi9jb21wb25lbnRzL1RlbGVwb3J0UmVzdW1lV3JhcHBlci5qcydcbiAgKVxuICByZXR1cm4gc2hvd1NldHVwRGlhbG9nPFRlbGVwb3J0UmVtb3RlUmVzcG9uc2UgfCBudWxsPihyb290LCBkb25lID0+IChcbiAgICA8VGVsZXBvcnRSZXN1bWVXcmFwcGVyXG4gICAgICBvbkNvbXBsZXRlPXtkb25lfVxuICAgICAgb25DYW5jZWw9eygpID0+IGRvbmUobnVsbCl9XG4gICAgICBzb3VyY2U9XCJjbGlBcmdcIlxuICAgIC8+XG4gICkpXG59XG5cbi8qKlxuICogU2l0ZSB+NDU5NzogVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2cgKHBpY2sgYSBsb2NhbCBjaGVja291dCBvZiB0aGUgdGFyZ2V0IHJlcG8pLlxuICogT3JpZ2luYWwgY2FsbGJhY2sgd2lyaW5nOiBvblNlbGVjdFBhdGg9e2RvbmV9LCBvbkNhbmNlbD17KCkgPT4gZG9uZShudWxsKX0uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsYXVuY2hUZWxlcG9ydFJlcG9NaXNtYXRjaERpYWxvZyhcbiAgcm9vdDogUm9vdCxcbiAgcHJvcHM6IHtcbiAgICB0YXJnZXRSZXBvOiBzdHJpbmdcbiAgICBpbml0aWFsUGF0aHM6IHN0cmluZ1tdXG4gIH0sXG4pOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgY29uc3QgeyBUZWxlcG9ydFJlcG9NaXNtYXRjaERpYWxvZyB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICcuL2NvbXBvbmVudHMvVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2cuanMnXG4gIClcbiAgcmV0dXJuIHNob3dTZXR1cERpYWxvZzxzdHJpbmcgfCBudWxsPihyb290LCBkb25lID0+IChcbiAgICA8VGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2dcbiAgICAgIHRhcmdldFJlcG89e3Byb3BzLnRhcmdldFJlcG99XG4gICAgICBpbml0aWFsUGF0aHM9e3Byb3BzLmluaXRpYWxQYXRoc31cbiAgICAgIG9uU2VsZWN0UGF0aD17ZG9uZX1cbiAgICAgIG9uQ2FuY2VsPXsoKSA9PiBkb25lKG51bGwpfVxuICAgIC8+XG4gICkpXG59XG5cbi8qKlxuICogU2l0ZSB+NDkwMzogUmVzdW1lQ29udmVyc2F0aW9uIG1vdW50IChpbnRlcmFjdGl2ZSBzZXNzaW9uIHBpY2tlcikuXG4gKiBVc2VzIHJlbmRlckFuZFJ1biwgTk9UIHNob3dTZXR1cERpYWxvZy4gV3JhcHMgaW4gPEFwcD48S2V5YmluZGluZ1NldHVwPi5cbiAqIFByZXNlcnZlcyBvcmlnaW5hbCBQcm9taXNlLmFsbCBwYXJhbGxlbGlzbSBiZXR3ZWVuIGdldFdvcmt0cmVlUGF0aHMgYW5kIGltcG9ydHMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsYXVuY2hSZXN1bWVDaG9vc2VyKFxuICByb290OiBSb290LFxuICBhcHBQcm9wczoge1xuICAgIGdldEZwc01ldHJpY3M6ICgpID0+IEZwc01ldHJpY3MgfCB1bmRlZmluZWRcbiAgICBzdGF0czogU3RhdHNTdG9yZVxuICAgIGluaXRpYWxTdGF0ZTogQXBwU3RhdGVcbiAgfSxcbiAgd29ya3RyZWVQYXRoc1Byb21pc2U6IFByb21pc2U8c3RyaW5nW10+LFxuICByZXN1bWVQcm9wczogT21pdDxSZXN1bWVDb252ZXJzYXRpb25Qcm9wcywgJ3dvcmt0cmVlUGF0aHMnPixcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBbd29ya3RyZWVQYXRocywgeyBSZXN1bWVDb252ZXJzYXRpb24gfSwgeyBBcHAgfV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgd29ya3RyZWVQYXRoc1Byb21pc2UsXG4gICAgaW1wb3J0KCcuL3NjcmVlbnMvUmVzdW1lQ29udmVyc2F0aW9uLmpzJyksXG4gICAgaW1wb3J0KCcuL2NvbXBvbmVudHMvQXBwLmpzJyksXG4gIF0pXG4gIGF3YWl0IHJlbmRlckFuZFJ1bihcbiAgICByb290LFxuICAgIDxBcHBcbiAgICAgIGdldEZwc01ldHJpY3M9e2FwcFByb3BzLmdldEZwc01ldHJpY3N9XG4gICAgICBzdGF0cz17YXBwUHJvcHMuc3RhdHN9XG4gICAgICBpbml0aWFsU3RhdGU9e2FwcFByb3BzLmluaXRpYWxTdGF0ZX1cbiAgICA+XG4gICAgICA8S2V5YmluZGluZ1NldHVwPlxuICAgICAgICA8UmVzdW1lQ29udmVyc2F0aW9uIHsuLi5yZXN1bWVQcm9wc30gd29ya3RyZWVQYXRocz17d29ya3RyZWVQYXRoc30gLz5cbiAgICAgIDwvS2V5YmluZGluZ1NldHVwPlxuICAgIDwvQXBwPixcbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBT0EsS0FBSyxNQUFNLE9BQU87QUFDekIsY0FBY0MsZ0JBQWdCLFFBQVEsaUNBQWlDO0FBQ3ZFLGNBQWNDLFVBQVUsUUFBUSxvQkFBb0I7QUFDcEQsY0FBY0MsSUFBSSxRQUFRLFVBQVU7QUFDcEMsU0FBU0MsWUFBWSxFQUFFQyxlQUFlLFFBQVEseUJBQXlCO0FBQ3ZFLFNBQVNDLGVBQWUsUUFBUSwwQ0FBMEM7QUFDMUUsY0FB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
@@ -39,7 +39,7 @@ async function main(): Promise<void> {
39
39
  if (args.length === 1 && (args[0] === '--version' || args[0] === '-v' || args[0] === '-V')) {
40
40
  // MACRO.VERSION is inlined at build time
41
41
  // biome-ignore lint/suspicious/noConsole:: intentional console output
42
- console.log(`xcode v3.1.1 — AI coding assistant with XMem memory`);
42
+ console.log(`xcode v3.1.2 — AI coding assistant with XMem memory`);
43
43
  return;
44
44
  }
45
45
 
package/macro.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // Build-time macros - stubbed for development
2
2
 
3
3
  export const MACRO = {
4
- VERSION: '3.1.1',
4
+ VERSION: '3.1.2',
5
5
  VERSION_CHANGELOG: '',
6
6
  NATIVE_PACKAGE_URL: '@anthropic-ai/claude-code-native',
7
7
  CLI_BIN_PATH: './cli.tsx',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xortex/xcode",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "description": "XCode - AI-powered coding assistant with XMem long-term memory. Supports Claude, Gemini, Kimi, DeepSeek via OpenRouter.",
5
5
  "main": "main.tsx",
6
6
  "bin": {
@@ -43,11 +43,15 @@
43
43
  "tsconfig.json",
44
44
  "macro.ts",
45
45
  "main.tsx",
46
+ "ink.ts",
46
47
  "commands.ts",
47
48
  "context.ts",
48
49
  "cost-tracker.ts",
50
+ "costHook.ts",
49
51
  "history.ts",
50
52
  "interactiveHelpers.tsx",
53
+ "replLauncher.tsx",
54
+ "dialogLaunchers.tsx",
51
55
  "QueryEngine.ts",
52
56
  "query.ts",
53
57
  "setup.ts",
@@ -55,7 +59,7 @@
55
59
  "Task.ts",
56
60
  "Tool.ts",
57
61
  "tools.ts",
58
- "ink.ts",
62
+ "projectOnboardingState.ts",
59
63
  "README.md",
60
64
  "LICENSE"
61
65
  ],
@@ -0,0 +1,83 @@
1
+ import memoize from 'lodash-es/memoize.js'
2
+ import { join } from 'path'
3
+ import {
4
+ getCurrentProjectConfig,
5
+ saveCurrentProjectConfig,
6
+ } from './utils/config.js'
7
+ import { getCwd } from './utils/cwd.js'
8
+ import { isDirEmpty } from './utils/file.js'
9
+ import { getFsImplementation } from './utils/fsOperations.js'
10
+
11
+ export type Step = {
12
+ key: string
13
+ text: string
14
+ isComplete: boolean
15
+ isCompletable: boolean
16
+ isEnabled: boolean
17
+ }
18
+
19
+ export function getSteps(): Step[] {
20
+ const hasClaudeMd = getFsImplementation().existsSync(
21
+ join(getCwd(), 'CLAUDE.md'),
22
+ )
23
+ const isWorkspaceDirEmpty = isDirEmpty(getCwd())
24
+
25
+ return [
26
+ {
27
+ key: 'workspace',
28
+ text: 'Ask Claude to create a new app or clone a repository',
29
+ isComplete: false,
30
+ isCompletable: true,
31
+ isEnabled: isWorkspaceDirEmpty,
32
+ },
33
+ {
34
+ key: 'claudemd',
35
+ text: 'Run /init to create a CLAUDE.md file with instructions for Claude',
36
+ isComplete: hasClaudeMd,
37
+ isCompletable: true,
38
+ isEnabled: !isWorkspaceDirEmpty,
39
+ },
40
+ ]
41
+ }
42
+
43
+ export function isProjectOnboardingComplete(): boolean {
44
+ return getSteps()
45
+ .filter(({ isCompletable, isEnabled }) => isCompletable && isEnabled)
46
+ .every(({ isComplete }) => isComplete)
47
+ }
48
+
49
+ export function maybeMarkProjectOnboardingComplete(): void {
50
+ // Short-circuit on cached config — isProjectOnboardingComplete() hits
51
+ // the filesystem, and REPL.tsx calls this on every prompt submit.
52
+ if (getCurrentProjectConfig().hasCompletedProjectOnboarding) {
53
+ return
54
+ }
55
+ if (isProjectOnboardingComplete()) {
56
+ saveCurrentProjectConfig(current => ({
57
+ ...current,
58
+ hasCompletedProjectOnboarding: true,
59
+ }))
60
+ }
61
+ }
62
+
63
+ export const shouldShowProjectOnboarding = memoize((): boolean => {
64
+ const projectConfig = getCurrentProjectConfig()
65
+ // Short-circuit on cached config before isProjectOnboardingComplete()
66
+ // hits the filesystem — this runs during first render.
67
+ if (
68
+ projectConfig.hasCompletedProjectOnboarding ||
69
+ projectConfig.projectOnboardingSeenCount >= 4 ||
70
+ process.env.IS_DEMO
71
+ ) {
72
+ return false
73
+ }
74
+
75
+ return !isProjectOnboardingComplete()
76
+ })
77
+
78
+ export function incrementProjectOnboardingSeenCount(): void {
79
+ saveCurrentProjectConfig(current => ({
80
+ ...current,
81
+ projectOnboardingSeenCount: current.projectOnboardingSeenCount + 1,
82
+ }))
83
+ }
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ import type { StatsStore } from "./context/stats.js";
3
+ import type { Root } from "./ink.js";
4
+ import type { Props as REPLProps } from "./screens/REPL.js";
5
+ import type { AppState } from "./state/AppStateStore.js";
6
+ import type { FpsMetrics } from "./utils/fpsTracker.js";
7
+ type AppWrapperProps = {
8
+ getFpsMetrics: () => FpsMetrics | undefined;
9
+ stats?: StatsStore;
10
+ initialState: AppState;
11
+ };
12
+ export async function launchRepl(
13
+ root: Root,
14
+ appProps: AppWrapperProps,
15
+ replProps: REPLProps,
16
+ renderAndRun: (root: Root, element: React.ReactNode) => Promise<void>,
17
+ ): Promise<void> {
18
+ const { App } = await import("./components/App.js");
19
+ const { REPL } = await import("./screens/REPL.js");
20
+ await renderAndRun(
21
+ root,
22
+ <App {...appProps}>
23
+ <REPL {...replProps} />
24
+ </App>,
25
+ );
26
+ }
27
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlN0YXRzU3RvcmUiLCJSb290IiwiUHJvcHMiLCJSRVBMUHJvcHMiLCJBcHBTdGF0ZSIsIkZwc01ldHJpY3MiLCJBcHBXcmFwcGVyUHJvcHMiLCJnZXRGcHNNZXRyaWNzIiwic3RhdHMiLCJpbml0aWFsU3RhdGUiLCJsYXVuY2hSZXBsIiwicm9vdCIsImFwcFByb3BzIiwicmVwbFByb3BzIiwicmVuZGVyQW5kUnVuIiwiZWxlbWVudCIsIlJlYWN0Tm9kZSIsIlByb21pc2UiLCJBcHAiLCJSRVBMIl0sInNvdXJjZXMiOlsicmVwbExhdW5jaGVyLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IFN0YXRzU3RvcmUgfSBmcm9tICcuL2NvbnRleHQvc3RhdHMuanMnXG5pbXBvcnQgdHlwZSB7IFJvb3QgfSBmcm9tICcuL2luay5qcydcbmltcG9ydCB0eXBlIHsgUHJvcHMgYXMgUkVQTFByb3BzIH0gZnJvbSAnLi9zY3JlZW5zL1JFUEwuanMnXG5pbXBvcnQgdHlwZSB7IEFwcFN0YXRlIH0gZnJvbSAnLi9zdGF0ZS9BcHBTdGF0ZVN0b3JlLmpzJ1xuaW1wb3J0IHR5cGUgeyBGcHNNZXRyaWNzIH0gZnJvbSAnLi91dGlscy9mcHNUcmFja2VyLmpzJ1xuXG50eXBlIEFwcFdyYXBwZXJQcm9wcyA9IHtcbiAgZ2V0RnBzTWV0cmljczogKCkgPT4gRnBzTWV0cmljcyB8IHVuZGVmaW5lZFxuICBzdGF0cz86IFN0YXRzU3RvcmVcbiAgaW5pdGlhbFN0YXRlOiBBcHBTdGF0ZVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGF1bmNoUmVwbChcbiAgcm9vdDogUm9vdCxcbiAgYXBwUHJvcHM6IEFwcFdyYXBwZXJQcm9wcyxcbiAgcmVwbFByb3BzOiBSRVBMUHJvcHMsXG4gIHJlbmRlckFuZFJ1bjogKHJvb3Q6IFJvb3QsIGVsZW1lbnQ6IFJlYWN0LlJlYWN0Tm9kZSkgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IEFwcCB9ID0gYXdhaXQgaW1wb3J0KCcuL2NvbXBvbmVudHMvQXBwLmpzJylcbiAgY29uc3QgeyBSRVBMIH0gPSBhd2FpdCBpbXBvcnQoJy4vc2NyZWVucy9SRVBMLmpzJylcbiAgYXdhaXQgcmVuZGVyQW5kUnVuKFxuICAgIHJvb3QsXG4gICAgPEFwcCB7Li4uYXBwUHJvcHN9PlxuICAgICAgPFJFUEwgey4uLnJlcGxQcm9wc30gLz5cbiAgICA8L0FwcD4sXG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsS0FBSyxNQUFNLE9BQU87QUFDekIsY0FBY0MsVUFBVSxRQUFRLG9CQUFvQjtBQUNwRCxjQUFjQyxJQUFJLFFBQVEsVUFBVTtBQUNwQyxjQUFjQyxLQUFLLElBQUlDLFNBQVMsUUFBUSxtQkFBbUI7QUFDM0QsY0FBY0MsUUFBUSxRQUFRLDBCQUEwQjtBQUN4RCxjQUFjQyxVQUFVLFFBQVEsdUJBQXVCO0FBRXZELEtBQUtDLGVBQWUsR0FBRztFQUNyQkMsYUFBYSxFQUFFLEdBQUcsR0FBR0YsVUFBVSxHQUFHLFNBQVM7RUFDM0NHLEtBQUssQ0FBQyxFQUFFUixVQUFVO0VBQ2xCUyxZQUFZLEVBQUVMLFFBQVE7QUFDeEIsQ0FBQztBQUVELE9BQU8sZUFBZU0sVUFBVUEsQ0FDOUJDLElBQUksRUFBRVYsSUFBSSxFQUNWVyxRQUFRLEVBQUVOLGVBQWUsRUFDekJPLFNBQVMsRUFBRVYsU0FBUyxFQUNwQlcsWUFBWSxFQUFFLENBQUNILElBQUksRUFBRVYsSUFBSSxFQUFFYyxPQUFPLEVBQUVoQixLQUFLLENBQUNpQixTQUFTLEVBQUUsR0FBR0MsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUN0RSxFQUFFQSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7RUFDZixNQUFNO0lBQUVDO0VBQUksQ0FBQyxHQUFHLE1BQU0sTUFBTSxDQUFDLHFCQUFxQixDQUFDO0VBQ25ELE1BQU07SUFBRUM7RUFBSyxDQUFDLEdBQUcsTUFBTSxNQUFNLENBQUMsbUJBQW1CLENBQUM7RUFDbEQsTUFBTUwsWUFBWSxDQUNoQkgsSUFBSSxFQUNKLENBQUMsR0FBRyxDQUFDLElBQUlDLFFBQVEsQ0FBQztBQUN0QixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUlDLFNBQVMsQ0FBQztBQUMxQixJQUFJLEVBQUUsR0FBRyxDQUNQLENBQUM7QUFDSCIsImlnbm9yZUxpc3QiOltdfQ==