centaurus-cli 2.9.3 → 2.9.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/dist/cli-adapter.d.ts +74 -10
- package/dist/cli-adapter.d.ts.map +1 -1
- package/dist/cli-adapter.js +898 -244
- package/dist/cli-adapter.js.map +1 -1
- package/dist/commands/CommandParser.d.ts +1 -1
- package/dist/commands/CommandParser.d.ts.map +1 -1
- package/dist/commands/CommandParser.js +113 -0
- package/dist/commands/CommandParser.js.map +1 -1
- package/dist/config/slash-commands.d.ts +2 -0
- package/dist/config/slash-commands.d.ts.map +1 -1
- package/dist/config/slash-commands.js +28 -0
- package/dist/config/slash-commands.js.map +1 -1
- package/dist/context/context-manager.d.ts +7 -1
- package/dist/context/context-manager.d.ts.map +1 -1
- package/dist/context/context-manager.js +14 -1
- package/dist/context/context-manager.js.map +1 -1
- package/dist/context/handlers/docker-handler.d.ts +11 -0
- package/dist/context/handlers/docker-handler.d.ts.map +1 -1
- package/dist/context/handlers/docker-handler.js +159 -14
- package/dist/context/handlers/docker-handler.js.map +1 -1
- package/dist/context/handlers/ssh-handler.d.ts +20 -0
- package/dist/context/handlers/ssh-handler.d.ts.map +1 -1
- package/dist/context/handlers/ssh-handler.js +129 -1
- package/dist/context/handlers/ssh-handler.js.map +1 -1
- package/dist/context/subshell-handler.d.ts +15 -0
- package/dist/context/subshell-handler.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/services/ai-service-client.d.ts.map +1 -1
- package/dist/services/ai-service-client.js +33 -11
- package/dist/services/ai-service-client.js.map +1 -1
- package/dist/services/api-client.js +1 -1
- package/dist/services/api-client.js.map +1 -1
- package/dist/services/local-chat-storage.d.ts +3 -1
- package/dist/services/local-chat-storage.d.ts.map +1 -1
- package/dist/services/local-chat-storage.js +8 -3
- package/dist/services/local-chat-storage.js.map +1 -1
- package/dist/services/warpify-detector.d.ts +43 -0
- package/dist/services/warpify-detector.d.ts.map +1 -0
- package/dist/services/warpify-detector.js +203 -0
- package/dist/services/warpify-detector.js.map +1 -0
- package/dist/services/workflow-storage.d.ts +72 -0
- package/dist/services/workflow-storage.d.ts.map +1 -0
- package/dist/services/workflow-storage.js +239 -0
- package/dist/services/workflow-storage.js.map +1 -0
- package/dist/tools/command.d.ts.map +1 -1
- package/dist/tools/command.js +106 -38
- package/dist/tools/command.js.map +1 -1
- package/dist/tools/enter-remote-session.d.ts +13 -0
- package/dist/tools/enter-remote-session.d.ts.map +1 -0
- package/dist/tools/enter-remote-session.js +226 -0
- package/dist/tools/enter-remote-session.js.map +1 -0
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +9 -2
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/grep-search.d.ts +104 -31
- package/dist/tools/grep-search.d.ts.map +1 -1
- package/dist/tools/grep-search.js +779 -431
- package/dist/tools/grep-search.js.map +1 -1
- package/dist/tools/workflow-tool.d.ts +11 -0
- package/dist/tools/workflow-tool.d.ts.map +1 -0
- package/dist/tools/workflow-tool.js +87 -0
- package/dist/tools/workflow-tool.js.map +1 -0
- package/dist/types/workflow.d.ts +110 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +8 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/ui/components/App.d.ts +10 -1
- package/dist/ui/components/App.d.ts.map +1 -1
- package/dist/ui/components/App.js +135 -8
- package/dist/ui/components/App.js.map +1 -1
- package/dist/ui/components/Breadcrumbs.d.ts +4 -3
- package/dist/ui/components/Breadcrumbs.d.ts.map +1 -1
- package/dist/ui/components/Breadcrumbs.js +80 -54
- package/dist/ui/components/Breadcrumbs.js.map +1 -1
- package/dist/ui/components/ConnectionStatusMessage.js +2 -2
- package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
- package/dist/ui/components/InputBox.d.ts +1 -0
- package/dist/ui/components/InputBox.d.ts.map +1 -1
- package/dist/ui/components/InputBox.js +226 -19
- package/dist/ui/components/InputBox.js.map +1 -1
- package/dist/ui/components/InteractiveShell.d.ts +4 -0
- package/dist/ui/components/InteractiveShell.d.ts.map +1 -1
- package/dist/ui/components/InteractiveShell.js +52 -15
- package/dist/ui/components/InteractiveShell.js.map +1 -1
- package/dist/ui/components/KeyboardHelp.d.ts.map +1 -1
- package/dist/ui/components/KeyboardHelp.js +14 -6
- package/dist/ui/components/KeyboardHelp.js.map +1 -1
- package/dist/ui/components/ToolExecutionMessage.d.ts.map +1 -1
- package/dist/ui/components/ToolExecutionMessage.js +165 -27
- package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
- package/dist/ui/components/WorkflowCreatorScreen.d.ts +25 -0
- package/dist/ui/components/WorkflowCreatorScreen.d.ts.map +1 -0
- package/dist/ui/components/WorkflowCreatorScreen.js +164 -0
- package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -0
- package/dist/utils/ansi-encoder.d.ts.map +1 -1
- package/dist/utils/ansi-encoder.js +7 -0
- package/dist/utils/ansi-encoder.js.map +1 -1
- package/dist/utils/editor-utils.d.ts +9 -0
- package/dist/utils/editor-utils.d.ts.map +1 -1
- package/dist/utils/editor-utils.js +105 -0
- package/dist/utils/editor-utils.js.map +1 -1
- package/dist/utils/input-classifier.d.ts.map +1 -1
- package/dist/utils/input-classifier.js +2 -1
- package/dist/utils/input-classifier.js.map +1 -1
- package/dist/utils/terminal-output.d.ts +3 -1
- package/dist/utils/terminal-output.d.ts.map +1 -1
- package/dist/utils/terminal-output.js +138 -157
- package/dist/utils/terminal-output.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,62 +1,88 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
+
// Get abbreviated breadcrumb (just the type) for parent sessions
|
|
4
|
+
const getAbbreviatedBreadcrumb = (context) => {
|
|
5
|
+
const typeColors = {
|
|
6
|
+
ssh: 'cyan',
|
|
7
|
+
wsl: 'yellow',
|
|
8
|
+
docker: 'blue',
|
|
9
|
+
local: 'gray'
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
label: context.type,
|
|
13
|
+
color: typeColors[context.type] || 'cyan'
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
// Get full breadcrumb with metadata for the current/active session
|
|
17
|
+
const getContextBreadcrumbs = (context) => {
|
|
18
|
+
// Get breadcrumbs from handler if available
|
|
19
|
+
if (context.handler?.getBreadcrumbs) {
|
|
20
|
+
const crumbs = context.handler.getBreadcrumbs();
|
|
21
|
+
if (crumbs.length > 0)
|
|
22
|
+
return crumbs;
|
|
23
|
+
}
|
|
24
|
+
// Default logic based on type
|
|
25
|
+
const typeColors = {
|
|
26
|
+
ssh: 'cyan',
|
|
27
|
+
wsl: 'yellow',
|
|
28
|
+
docker: 'blue',
|
|
29
|
+
local: 'gray'
|
|
30
|
+
};
|
|
31
|
+
const info = {
|
|
32
|
+
label: context.type,
|
|
33
|
+
color: typeColors[context.type] || 'cyan'
|
|
34
|
+
};
|
|
35
|
+
// Enhance label with metadata
|
|
36
|
+
if (context.type === 'ssh' && context.metadata.username) {
|
|
37
|
+
info.label = `${context.metadata.username}@${context.metadata.hostname || 'host'}`;
|
|
38
|
+
}
|
|
39
|
+
else if (context.type === 'wsl' && context.metadata.distroName) {
|
|
40
|
+
info.label = `wsl:${context.metadata.distroName}`;
|
|
41
|
+
}
|
|
42
|
+
else if (context.type === 'docker' && context.metadata.containerId) {
|
|
43
|
+
info.label = `docker:${context.metadata.containerId.substring(0, 8)}`;
|
|
44
|
+
}
|
|
45
|
+
return [info];
|
|
46
|
+
};
|
|
3
47
|
/**
|
|
4
|
-
* Breadcrumbs component displays the current subshell context
|
|
5
|
-
* Shows visual indicators for
|
|
48
|
+
* Breadcrumbs component displays the current subshell context stack
|
|
49
|
+
* Shows visual indicators for nested environments relative to local
|
|
6
50
|
*/
|
|
7
|
-
export const Breadcrumbs = ({ context }) => {
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
51
|
+
export const Breadcrumbs = ({ context, stack }) => {
|
|
52
|
+
// Use stack if available, otherwise fallback to single context
|
|
53
|
+
let contexts = stack || (context ? [context] : []);
|
|
54
|
+
// Filter out local context if it's the base of a remote stack (standard case)
|
|
55
|
+
// We only want to show the "remote path"
|
|
56
|
+
if (contexts.length > 1 && contexts[0].type === 'local') {
|
|
57
|
+
contexts = contexts.slice(1);
|
|
11
58
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (breadcrumbs.length === 0) {
|
|
16
|
-
const defaultBreadcrumbs = [];
|
|
17
|
-
// Add type breadcrumb with appropriate color
|
|
18
|
-
const typeColors = {
|
|
19
|
-
ssh: 'cyan',
|
|
20
|
-
wsl: 'yellow',
|
|
21
|
-
docker: 'blue',
|
|
22
|
-
};
|
|
23
|
-
defaultBreadcrumbs.push({
|
|
24
|
-
label: context.type,
|
|
25
|
-
color: typeColors[context.type] || 'cyan',
|
|
26
|
-
});
|
|
27
|
-
// Add hostname/username for SSH
|
|
28
|
-
if (context.type === 'ssh' && context.metadata.username && context.metadata.hostname) {
|
|
29
|
-
defaultBreadcrumbs.push({
|
|
30
|
-
label: `${context.metadata.username}@${context.metadata.hostname}`,
|
|
31
|
-
color: 'cyan',
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
// Add distribution name for WSL
|
|
35
|
-
if (context.type === 'wsl' && context.metadata.distroName) {
|
|
36
|
-
defaultBreadcrumbs.push({
|
|
37
|
-
label: context.metadata.distroName,
|
|
38
|
-
color: 'yellow',
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
// Add container ID for Docker
|
|
42
|
-
if (context.type === 'docker' && context.metadata.containerId) {
|
|
43
|
-
defaultBreadcrumbs.push({
|
|
44
|
-
label: context.metadata.containerId.substring(0, 12), // Show first 12 chars like Docker CLI
|
|
45
|
-
color: 'blue',
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
return (React.createElement(Box, { marginRight: 1 }, defaultBreadcrumbs.map((crumb, i) => (React.createElement(Box, { key: i, marginRight: 1 },
|
|
49
|
-
React.createElement(Text, { color: crumb.color || 'cyan', bold: true },
|
|
50
|
-
"[",
|
|
51
|
-
crumb.label,
|
|
52
|
-
"]"))))));
|
|
59
|
+
else if (contexts.length === 1 && contexts[0].type === 'local') {
|
|
60
|
+
// If we're just local, render nothing (InputBox handles CWD)
|
|
61
|
+
return null;
|
|
53
62
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
if (contexts.length === 0)
|
|
64
|
+
return null;
|
|
65
|
+
// Determine if this is the last context (current/active session)
|
|
66
|
+
const isLastContext = (ctxIndex) => ctxIndex === contexts.length - 1;
|
|
67
|
+
return (React.createElement(Box, { marginRight: 1 }, contexts.map((ctx, ctxIndex) => {
|
|
68
|
+
// For parent sessions (not the last one), use abbreviated labels
|
|
69
|
+
// For the current/active session (last one), show full details
|
|
70
|
+
const crumbs = isLastContext(ctxIndex)
|
|
71
|
+
? getContextBreadcrumbs(ctx)
|
|
72
|
+
: [getAbbreviatedBreadcrumb(ctx)];
|
|
73
|
+
return (React.createElement(Box, { key: ctx.sessionId || ctxIndex, flexDirection: "row" },
|
|
74
|
+
ctxIndex > 0 && (React.createElement(Box, { marginX: 1 },
|
|
75
|
+
React.createElement(Text, { color: "gray" }, "\u203A"))),
|
|
76
|
+
crumbs.map((info, crumbIndex) => {
|
|
77
|
+
// Only bold the very last item of the very last context
|
|
78
|
+
const isLast = isLastContext(ctxIndex) && crumbIndex === crumbs.length - 1;
|
|
79
|
+
return (React.createElement(Box, { key: `${ctxIndex}-${crumbIndex}`, flexDirection: "row" },
|
|
80
|
+
crumbIndex > 0 && React.createElement(Box, { width: 1 }),
|
|
81
|
+
React.createElement(Text, { color: info.color || 'cyan', bold: isLast },
|
|
82
|
+
"[",
|
|
83
|
+
info.label,
|
|
84
|
+
"]")));
|
|
85
|
+
})));
|
|
86
|
+
})));
|
|
61
87
|
};
|
|
62
88
|
//# sourceMappingURL=Breadcrumbs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../../src/ui/components/Breadcrumbs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../../src/ui/components/Breadcrumbs.tsx"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ export const ConnectionStatusMessage = React.memo(({ status }) => {
|
|
|
21
21
|
React.createElement(Text, { color: "#00ccff" },
|
|
22
22
|
React.createElement(Spinner, { type: "dots" })),
|
|
23
23
|
React.createElement(Text, { color: "#9945FF" },
|
|
24
|
-
"
|
|
24
|
+
" Tunnelling to ",
|
|
25
25
|
getTypeLabel(),
|
|
26
26
|
" environment..."))));
|
|
27
27
|
}
|
|
@@ -31,7 +31,7 @@ export const ConnectionStatusMessage = React.memo(({ status }) => {
|
|
|
31
31
|
React.createElement(Box, null,
|
|
32
32
|
React.createElement(Text, { color: "#00cc66", bold: true }, "\u2713"),
|
|
33
33
|
React.createElement(Text, { color: "#00cc66" },
|
|
34
|
-
"
|
|
34
|
+
" Established Wormhole to ",
|
|
35
35
|
getTypeLabel(),
|
|
36
36
|
" environment"),
|
|
37
37
|
status.connectionString && (React.createElement(Text, { color: "#666666" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConnectionStatusMessage.js","sourceRoot":"","sources":["../../../src/ui/components/ConnectionStatusMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;AAalC;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA2C,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACrG,MAAM,YAAY,GAAG,GAAG,EAAE;QACtB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC;YACzB,KAAK,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC;YACzB,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC/B,OAAO,CAAC,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC;QAChC,CAAC;IACL,CAAC,CAAC;IAEF,mCAAmC;IACnC,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QACjC,OAAO,CACH,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,EAAC,YAAY;YACtH,oBAAC,GAAG;gBACA,oBAAC,IAAI,IAAC,KAAK,EAAC,SAAS;oBAAC,oBAAC,OAAO,IAAC,IAAI,EAAC,MAAM,GAAG,CAAO;gBACpD,oBAAC,IAAI,IAAC,KAAK,EAAC,SAAS;;oBAAiB,YAAY,EAAE;sCAAuB,CACzE,CACJ,CACT,CAAC;IACN,CAAC;IAED,2CAA2C;IAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,CACH,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,SAAS,EAAC,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,EAAC,YAAY;YACtH,oBAAC,GAAG;gBACA,oBAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,mBAAS;gBACnC,oBAAC,IAAI,IAAC,KAAK,EAAC,SAAS;;
|
|
1
|
+
{"version":3,"file":"ConnectionStatusMessage.js","sourceRoot":"","sources":["../../../src/ui/components/ConnectionStatusMessage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../../src/ui/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAWzD,OAAO,EAAyC,cAAc,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"InputBox.d.ts","sourceRoot":"","sources":["../../../src/ui/components/InputBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAIpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAWzD,OAAO,EAAyC,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAM5G,UAAU,aAAa;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,eAAe,EAAE,CAAC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IACpE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AA+CD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoqE3C,CAAC"}
|
|
@@ -14,6 +14,7 @@ import { filterCommands } from '../../config/slash-commands.js';
|
|
|
14
14
|
import { getClipboardImages } from '../../services/clipboard-service.js';
|
|
15
15
|
import { useTerminalDimensions, TERMINAL_HEIGHT_CONSTANTS } from '../../hooks/useTerminalDimensions.js';
|
|
16
16
|
import { AIAutocompleteAgent, AI_AUTOCOMPLETE_DEBOUNCE_MS } from '../../services/ai-autocomplete-agent.js';
|
|
17
|
+
import { workflowStorage } from '../../services/workflow-storage.js';
|
|
17
18
|
const getVisualLines = (text, width) => {
|
|
18
19
|
const logicalLines = text.split('\n');
|
|
19
20
|
const visualLines = [];
|
|
@@ -51,7 +52,7 @@ const getVisualLines = (text, width) => {
|
|
|
51
52
|
});
|
|
52
53
|
return visualLines;
|
|
53
54
|
};
|
|
54
|
-
export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...', autoAcceptMode, model, planMode = false, commandMode = false, backgroundMode = false, currentWorkingDirectory, commandHistory = [], onToggleAutoAccept, onToggleCommandMode, onToggleBackgroundMode, isActive = true, subshellContext, currentTokens = 0, maxTokens = 1000000, contextLimitReached = false, isShellRunning = false, backgroundTaskCount = 0, initialValue = '', onValueChange, onSetAutoModeSetup, sessionQuotaExhausted = false, sessionQuotaTimeRemaining = '', subAgentCount = 0, aiAutoSuggestEnabled = false, sessionCommands = [] }) => {
|
|
55
|
+
export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...', autoAcceptMode, model, planMode = false, commandMode = false, backgroundMode = false, currentWorkingDirectory, commandHistory = [], onToggleAutoAccept, onToggleCommandMode, onToggleBackgroundMode, isActive = true, subshellContext, subshellContextStack, currentTokens = 0, maxTokens = 1000000, contextLimitReached = false, isShellRunning = false, backgroundTaskCount = 0, initialValue = '', onValueChange, onSetAutoModeSetup, sessionQuotaExhausted = false, sessionQuotaTimeRemaining = '', subAgentCount = 0, aiAutoSuggestEnabled = false, sessionCommands = [] }) => {
|
|
55
56
|
// Use initialValue for first mount, but manage state internally after that
|
|
56
57
|
const [value, setValueInternal] = useState(initialValue);
|
|
57
58
|
const [cursorOffset, setCursorOffset] = useState(0);
|
|
@@ -564,6 +565,68 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
564
565
|
setCursorOffset(newValue.length);
|
|
565
566
|
setSlashAutocompleteVisible(false);
|
|
566
567
|
}
|
|
568
|
+
else if (value.startsWith('/workflow new ') || value.startsWith('/wf new ')) {
|
|
569
|
+
// We're in workflow new subcommand mode (manual or learn-workflow)
|
|
570
|
+
const prefix = value.startsWith('/workflow new ') ? '/workflow new ' : '/wf new ';
|
|
571
|
+
const newValue = `${prefix}${selected.name}`;
|
|
572
|
+
setValue(newValue);
|
|
573
|
+
setCursorOffset(newValue.length);
|
|
574
|
+
setSlashAutocompleteVisible(false);
|
|
575
|
+
}
|
|
576
|
+
else if (value.startsWith('/workflow ') || value.startsWith('/wf ')) {
|
|
577
|
+
// Check if we're in workflow name selection mode (after run/view/delete)
|
|
578
|
+
const workflowNameMatch = value.match(/^\/(?:workflow|wf)\s+(run|view|delete)\s+/);
|
|
579
|
+
if (workflowNameMatch) {
|
|
580
|
+
// We're selecting a workflow name
|
|
581
|
+
const prefix = value.match(/^\/(?:workflow|wf)\s+(?:run|view|delete)\s+/)?.[0] || '';
|
|
582
|
+
const newValue = `${prefix}${selected.name}`;
|
|
583
|
+
setValue(newValue);
|
|
584
|
+
setCursorOffset(newValue.length);
|
|
585
|
+
setSlashAutocompleteVisible(false);
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
// We're selecting a workflow subcommand
|
|
589
|
+
const prefix = value.startsWith('/workflow ') ? '/workflow ' : '/wf ';
|
|
590
|
+
const newValue = `${prefix}${selected.name} `;
|
|
591
|
+
setValue(newValue);
|
|
592
|
+
setCursorOffset(newValue.length);
|
|
593
|
+
// For run/view/delete, show workflow names immediately
|
|
594
|
+
if (selected.name === 'run' || selected.name === 'view' || selected.name === 'delete') {
|
|
595
|
+
const workflows = workflowStorage.list();
|
|
596
|
+
const matchingWorkflows = workflows
|
|
597
|
+
.slice(0, 10)
|
|
598
|
+
.map(wf => ({
|
|
599
|
+
name: wf.name,
|
|
600
|
+
description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`
|
|
601
|
+
}));
|
|
602
|
+
if (matchingWorkflows.length > 0) {
|
|
603
|
+
setSlashAutocompleteCommands(matchingWorkflows);
|
|
604
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
605
|
+
setSlashAutocompleteScrollOffset(0);
|
|
606
|
+
// Keep autocomplete visible
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
setSlashAutocompleteVisible(false);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
else if (selected.name === 'new') {
|
|
613
|
+
// For 'new' subcommand, show manual/learn-workflow options
|
|
614
|
+
const subcommandMatches = filterCommands('workflow new ');
|
|
615
|
+
if (subcommandMatches.length > 0) {
|
|
616
|
+
setSlashAutocompleteCommands(subcommandMatches);
|
|
617
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
618
|
+
setSlashAutocompleteScrollOffset(0);
|
|
619
|
+
// Keep autocomplete visible for next level
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
setSlashAutocompleteVisible(false);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
setSlashAutocompleteVisible(false);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
567
630
|
else if (value.startsWith('/settings auto-suggest ')) {
|
|
568
631
|
// We're selecting an auto-suggest option (on/off)
|
|
569
632
|
const newValue = `/settings auto-suggest ${selected.name}`;
|
|
@@ -683,6 +746,18 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
683
746
|
setSlashAutocompleteVisible(false);
|
|
684
747
|
}
|
|
685
748
|
}
|
|
749
|
+
else if (selected.name === 'workflow' || selected.name === 'wf') {
|
|
750
|
+
const subcommandMatches = filterCommands('workflow ');
|
|
751
|
+
if (subcommandMatches.length > 0) {
|
|
752
|
+
setSlashAutocompleteCommands(subcommandMatches);
|
|
753
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
754
|
+
setSlashAutocompleteScrollOffset(0);
|
|
755
|
+
// Keep autocomplete visible for subcommands
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
setSlashAutocompleteVisible(false);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
686
761
|
else {
|
|
687
762
|
setSlashAutocompleteVisible(false);
|
|
688
763
|
}
|
|
@@ -769,7 +844,10 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
769
844
|
}
|
|
770
845
|
// Alt+V: Paste image from clipboard
|
|
771
846
|
// Detect Alt+V on Windows/Linux (key.meta is often Alt on Windows in Ink)
|
|
772
|
-
|
|
847
|
+
// On Mac, we want to support Cmd+V explicitly as requested ("make alt key combinations work with cmd key")
|
|
848
|
+
// Note: Cmd+V is often captured by the terminal for text paste, but if it gets through, we handle it.
|
|
849
|
+
// Option+V on Mac often sends '√', which we also support.
|
|
850
|
+
const isAltV = (key.meta && input === 'v') || (input === '√');
|
|
773
851
|
if (isAltV && !commandMode) {
|
|
774
852
|
// Check clipboard for images asynchronously
|
|
775
853
|
(async () => {
|
|
@@ -797,15 +875,13 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
797
875
|
})();
|
|
798
876
|
return;
|
|
799
877
|
}
|
|
800
|
-
// DELETE WORD BACKWARDS
|
|
801
|
-
//
|
|
802
|
-
//
|
|
803
|
-
//
|
|
804
|
-
// 3. Ctrl + Delete - Works on all platforms (Ctrl+Backspace doesn't work on Windows/Ink)
|
|
805
|
-
// 4. Windows Ctrl+Del sends char code 127
|
|
878
|
+
// DELETE WORD BACKWARDS
|
|
879
|
+
// 1. Ctrl+W
|
|
880
|
+
// 2. Cmd+Backspace (Mac) - often mapped to delete line, but here we treat key.meta as modifier
|
|
881
|
+
// 3. Alt+Backspace (Windows/Linux)
|
|
806
882
|
const isDeleteWord = inputCharCode === 23 || // Ctrl+W
|
|
807
|
-
(key.meta && (key.backspace || key.delete)) || //
|
|
808
|
-
(key.ctrl && key.delete) || // Ctrl+Delete
|
|
883
|
+
(key.meta && (key.backspace || key.delete)) || // Cmd+Backspace (Mac) or Alt+Backspace (Win)
|
|
884
|
+
(key.ctrl && key.delete) || // Ctrl+Delete
|
|
809
885
|
(isWindows && inputCharCode === 127); // Windows: Ctrl+Del sends char 127
|
|
810
886
|
if (isDeleteWord) {
|
|
811
887
|
pushToUndoStack();
|
|
@@ -920,6 +996,59 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
920
996
|
setSlashAutocompleteVisible(false);
|
|
921
997
|
}
|
|
922
998
|
}
|
|
999
|
+
else if (newValue.match(/^\/workflow\s+(run|view|delete)\s+/) ||
|
|
1000
|
+
newValue.match(/^\/wf\s+(run|view|delete)\s+/)) {
|
|
1001
|
+
// Workflow name autocomplete (when user types "/workflow run " or similar)
|
|
1002
|
+
// This MUST come before the /workflow subcommand check since it's more specific
|
|
1003
|
+
const match = newValue.match(/^\/(?:workflow|wf)\s+(?:run|view|delete)\s+(.*)$/);
|
|
1004
|
+
const partialName = match ? match[1].toLowerCase() : '';
|
|
1005
|
+
const workflows = workflowStorage.list();
|
|
1006
|
+
const matchingWorkflows = workflows
|
|
1007
|
+
.filter(wf => wf.name.toLowerCase().includes(partialName))
|
|
1008
|
+
.slice(0, 10)
|
|
1009
|
+
.map(wf => ({
|
|
1010
|
+
name: wf.name,
|
|
1011
|
+
description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`
|
|
1012
|
+
}));
|
|
1013
|
+
if (matchingWorkflows.length > 0) {
|
|
1014
|
+
setSlashAutocompleteCommands(matchingWorkflows);
|
|
1015
|
+
setSlashAutocompleteVisible(true);
|
|
1016
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
1017
|
+
setSlashAutocompleteScrollOffset(0);
|
|
1018
|
+
}
|
|
1019
|
+
else {
|
|
1020
|
+
setSlashAutocompleteVisible(false);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
else if (newValue.match(/^\/workflow\s+new\s+/) ||
|
|
1024
|
+
newValue.match(/^\/wf\s+new\s+/)) {
|
|
1025
|
+
// Workflow new subcommand autocomplete (manual, learn-workflow)
|
|
1026
|
+
const fullQuery = newValue.slice(1);
|
|
1027
|
+
const matches = filterCommands(fullQuery);
|
|
1028
|
+
if (matches.length > 0) {
|
|
1029
|
+
setSlashAutocompleteCommands(matches);
|
|
1030
|
+
setSlashAutocompleteVisible(true);
|
|
1031
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
1032
|
+
setSlashAutocompleteScrollOffset(0);
|
|
1033
|
+
}
|
|
1034
|
+
else {
|
|
1035
|
+
setSlashAutocompleteVisible(false);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
else if (newValue.startsWith('/workflow ') || newValue.startsWith('/wf ')) {
|
|
1039
|
+
// Workflow subcommands (when user types "/workflow " or "/wf ")
|
|
1040
|
+
const fullQuery = newValue.slice(1);
|
|
1041
|
+
const matches = filterCommands(fullQuery);
|
|
1042
|
+
if (matches.length > 0) {
|
|
1043
|
+
setSlashAutocompleteCommands(matches);
|
|
1044
|
+
setSlashAutocompleteVisible(true);
|
|
1045
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
1046
|
+
setSlashAutocompleteScrollOffset(0);
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
setSlashAutocompleteVisible(false);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
923
1052
|
else {
|
|
924
1053
|
setSlashAutocompleteVisible(false);
|
|
925
1054
|
}
|
|
@@ -1324,8 +1453,18 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1324
1453
|
return;
|
|
1325
1454
|
}
|
|
1326
1455
|
if (key.leftArrow) {
|
|
1327
|
-
if (
|
|
1328
|
-
//
|
|
1456
|
+
if (isMac && key.meta) {
|
|
1457
|
+
// Mac: Cmd+Left -> Start of line (Home)
|
|
1458
|
+
setCursorOffset(0);
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
if (key.ctrl || (!isMac && key.meta)) {
|
|
1462
|
+
// Ctrl+Left (All) or Alt+Left (Win/Linux): Move word backwards
|
|
1463
|
+
// Note: On Mac, Option+Left is the standard for word back, but Ink doesn't expose 'alt'.
|
|
1464
|
+
// Users can use Ctrl+Left or rely on terminal mapping Option to Meta which effectively makes it key.meta
|
|
1465
|
+
// BUT if key.meta is Cmd on Mac, we map that to Home.
|
|
1466
|
+
// So standard Mac "Option+Left" might not work unless it sends Esc sequence or mapped to Ctrl.
|
|
1467
|
+
// We allow Ctrl+Left for Mac users.
|
|
1329
1468
|
let newOffset = cursorOffset;
|
|
1330
1469
|
if (newOffset > 0) {
|
|
1331
1470
|
// Skip whitespace backwards
|
|
@@ -1338,8 +1477,10 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1338
1477
|
}
|
|
1339
1478
|
setCursorOffset(newOffset);
|
|
1340
1479
|
}
|
|
1480
|
+
return;
|
|
1341
1481
|
}
|
|
1342
|
-
|
|
1482
|
+
// Standard Left Arrow
|
|
1483
|
+
if (cursorOffset > 0) {
|
|
1343
1484
|
setCursorOffset(cursorOffset - 1);
|
|
1344
1485
|
}
|
|
1345
1486
|
return;
|
|
@@ -1347,10 +1488,16 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1347
1488
|
if (key.rightArrow) {
|
|
1348
1489
|
// Autocomplete Logic (Only at end of line)
|
|
1349
1490
|
// AI suggestion takes priority over passive suggestion
|
|
1491
|
+
// Autocomplete Logic
|
|
1350
1492
|
const effectiveSuggestion = aiAutocompleteSuggestion || autocompleteSuggestion;
|
|
1351
1493
|
if (effectiveSuggestion && cursorOffset === value.length) {
|
|
1352
|
-
if (key.ctrl) {
|
|
1353
|
-
// Ctrl+Right: Accept FULL suggestion
|
|
1494
|
+
if (key.ctrl || (isMac && key.meta)) {
|
|
1495
|
+
// Ctrl+Right (Win) or Cmd+Right (Mac): Accept FULL suggestion
|
|
1496
|
+
// (Wait, Cmd+Right is usually End of Line on Mac. We should prioritize Navigation over Autocomplete?
|
|
1497
|
+
// Actually, if we are at end of line, End of Line does nothing. So we can use it for accept full?)
|
|
1498
|
+
// Convention: Right Arrow accepts word. Ctrl+Right accepts full?
|
|
1499
|
+
// On Mac, Cmd+Right is End. If at End, it's a no-op for nav.
|
|
1500
|
+
// Let's allow Cmd+Right to accept full IF at end.
|
|
1354
1501
|
setValue(effectiveSuggestion);
|
|
1355
1502
|
setCursorOffset(effectiveSuggestion.length);
|
|
1356
1503
|
setAutocompleteSuggestion(null);
|
|
@@ -1360,17 +1507,16 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1360
1507
|
else {
|
|
1361
1508
|
// Right: Accept NEXT WORD
|
|
1362
1509
|
const remaining = effectiveSuggestion.slice(value.length);
|
|
1363
|
-
// Match next chunk of non-whitespace
|
|
1510
|
+
// Match next chunk of non-whitespace
|
|
1364
1511
|
const match = remaining.match(/^(\s*\S+)/);
|
|
1365
1512
|
if (match) {
|
|
1366
1513
|
const toAdd = match[0];
|
|
1367
1514
|
const newValue = value + toAdd;
|
|
1368
1515
|
setValue(newValue);
|
|
1369
1516
|
setCursorOffset(newValue.length);
|
|
1370
|
-
return;
|
|
1517
|
+
return; // Done
|
|
1371
1518
|
}
|
|
1372
1519
|
else if (remaining.length > 0) {
|
|
1373
|
-
// Fallback: if only whitespace remains or regex fails, take it all
|
|
1374
1520
|
const newValue = value + remaining;
|
|
1375
1521
|
setValue(newValue);
|
|
1376
1522
|
setCursorOffset(newValue.length);
|
|
@@ -1378,6 +1524,29 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1378
1524
|
}
|
|
1379
1525
|
}
|
|
1380
1526
|
}
|
|
1527
|
+
// Navigation Logic
|
|
1528
|
+
if (isMac && key.meta) {
|
|
1529
|
+
// Cmd+Right -> End of line
|
|
1530
|
+
setCursorOffset(value.length);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
if ((!isMac && key.meta) || key.ctrl) {
|
|
1534
|
+
// Alt+Right (Win) or Ctrl+Right: Word Forward
|
|
1535
|
+
// (Note: Ink uses key.meta for Alt on Windows)
|
|
1536
|
+
let newOffset = cursorOffset;
|
|
1537
|
+
if (newOffset < value.length) {
|
|
1538
|
+
// Skip whitespace forwards
|
|
1539
|
+
while (newOffset < value.length && /\s/.test(value[newOffset])) {
|
|
1540
|
+
newOffset++;
|
|
1541
|
+
}
|
|
1542
|
+
// Skip non-whitespace forwards
|
|
1543
|
+
while (newOffset < value.length && !/\s/.test(value[newOffset])) {
|
|
1544
|
+
newOffset++;
|
|
1545
|
+
}
|
|
1546
|
+
setCursorOffset(newOffset);
|
|
1547
|
+
}
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1381
1550
|
// Navigation Logic (if not completing)
|
|
1382
1551
|
if (key.ctrl || key.meta) {
|
|
1383
1552
|
// Ctrl+Right / Meta+Right (Option+Right): Move word forwards
|
|
@@ -1537,6 +1706,44 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1537
1706
|
setSlashAutocompleteVisible(false);
|
|
1538
1707
|
}
|
|
1539
1708
|
}
|
|
1709
|
+
else if (newValue.match(/^\/workflow\s+(run|view|delete)\s+/) ||
|
|
1710
|
+
newValue.match(/^\/wf\s+(run|view|delete)\s+/)) {
|
|
1711
|
+
// Workflow name autocomplete (when user types "/workflow run " or similar)
|
|
1712
|
+
// This MUST come before the /workflow subcommand check since it's more specific
|
|
1713
|
+
const match = newValue.match(/^\/(?:workflow|wf)\s+(?:run|view|delete)\s+(.*)$/);
|
|
1714
|
+
const partialName = match ? match[1].toLowerCase() : '';
|
|
1715
|
+
const workflows = workflowStorage.list();
|
|
1716
|
+
const matchingWorkflows = workflows
|
|
1717
|
+
.filter(wf => wf.name.toLowerCase().includes(partialName))
|
|
1718
|
+
.slice(0, 10)
|
|
1719
|
+
.map(wf => ({
|
|
1720
|
+
name: wf.name,
|
|
1721
|
+
description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`
|
|
1722
|
+
}));
|
|
1723
|
+
if (matchingWorkflows.length > 0) {
|
|
1724
|
+
setSlashAutocompleteCommands(matchingWorkflows);
|
|
1725
|
+
setSlashAutocompleteVisible(true);
|
|
1726
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
1727
|
+
setSlashAutocompleteScrollOffset(0);
|
|
1728
|
+
}
|
|
1729
|
+
else {
|
|
1730
|
+
setSlashAutocompleteVisible(false);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
else if (newValue.startsWith('/workflow ') || newValue.startsWith('/wf ')) {
|
|
1734
|
+
// Workflow subcommands (when user types "/workflow " or "/wf ")
|
|
1735
|
+
const fullQuery = newValue.slice(1); // Remove leading "/", pass "workflow <subquery>" to filterCommands
|
|
1736
|
+
const matches = filterCommands(fullQuery);
|
|
1737
|
+
if (matches.length > 0) {
|
|
1738
|
+
setSlashAutocompleteCommands(matches);
|
|
1739
|
+
setSlashAutocompleteVisible(true);
|
|
1740
|
+
setSlashAutocompleteSelectedIndex(0);
|
|
1741
|
+
setSlashAutocompleteScrollOffset(0);
|
|
1742
|
+
}
|
|
1743
|
+
else {
|
|
1744
|
+
setSlashAutocompleteVisible(false);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1540
1747
|
else {
|
|
1541
1748
|
setSlashAutocompleteVisible(false);
|
|
1542
1749
|
}
|
|
@@ -1814,7 +2021,7 @@ export const InputBox = React.memo(({ onSubmit, placeholder = 'Ask anything...',
|
|
|
1814
2021
|
"#257aa5ff", paddingX: 1, paddingY: 0, width: "100%" },
|
|
1815
2022
|
React.createElement(Box, { marginY: 1, justifyContent: "space-between", width: "100%" },
|
|
1816
2023
|
React.createElement(Box, null,
|
|
1817
|
-
subshellContext && subshellContext.type !== 'local' && (React.createElement(Breadcrumbs, { context: subshellContext })),
|
|
2024
|
+
subshellContext && subshellContext.type !== 'local' && (React.createElement(Breadcrumbs, { context: subshellContext, stack: subshellContextStack })),
|
|
1818
2025
|
React.createElement(Text, { color: "#666666" }, "CWD: "),
|
|
1819
2026
|
React.createElement(Text, { color: "#00ccff", bold: true }, currentDir)),
|
|
1820
2027
|
React.createElement(Box, null,
|